package cn.zhentao.controller;

import cn.zhentao.entity.QuestionRecord;
import cn.zhentao.mapper.QuestionRecordMapper;
import cn.zhentao.mapper.SearchRecordMapper;
import cn.zhentao.mapper.TutorQuestionMapper;
import cn.zhentao.mapper.TutorSessionMapper;
import cn.zhentao.mapper.TutorMessageMapper;
import cn.zhentao.mapper.TutorLearningStatsMapper;

import cn.zhentao.pojo.TutorQuestion;
import cn.zhentao.pojo.TutorSession;
import cn.zhentao.pojo.TutorMessage;
import cn.zhentao.utils.AliyunOcrUtil;
import cn.zhentao.utils.ImageHashUtil;
import cn.zhentao.utils.RedisUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import cn.zhentao.service.AiChatService;
import cn.zhentao.service.SearchRecordService;
import cn.zhentao.service.MinioFileService;
import cn.zhentao.service.MinioService;
import cn.zhentao.service.VoiceFileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.Base64;

/**
 * 伴伴AI搜题系统控制器
 * 集成拍照搜题、错题管理、会话管理、学习统计等功能
 *
 * @author zhentao
 */
@RestController
@RequestMapping("/ai-tutor")
@Api(tags = "伴伴AI搜题系统")
@Slf4j
public class AiTutorController {

    @Autowired
    private AiChatService aiChatService;

    @Autowired
    private SearchRecordService searchRecordService;

    @Autowired
    private MinioFileService minioFileService;

    @Autowired
    private MinioService minioService;

    @Autowired
    private AliyunOcrUtil aliyunOcrUtil;

    @Autowired
    private QuestionRecordMapper questionRecordMapper;


    @Autowired
    private TutorQuestionMapper tutorQuestionMapper;

    @Autowired
    private TutorSessionMapper tutorSessionMapper;

    @Autowired
    private TutorMessageMapper tutorMessageMapper;

    @Autowired
    private VoiceFileService voiceFileService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 拍照搜题一体化功能 - 核心功能
     * 集成OCR识别、AI分析、相似题目生成、对话功能的完整解决方案
     *
     * @param userId 用户ID
     * @param sessionName 会话名称（可选）
     * @param imageFile 题目图片文件
     * @return 完整的搜题结果，包含解答、相似题目和对话会话
     */
    @PostMapping("/integrated-search")
    @ApiOperation(value = "拍照搜题一体化", notes = "上传题目图片，伴伴AI智能分析并生成详细解答、相似题目，支持后续对话和语音播报")
    public Map<String, Object> integratedQuestionSearch(
            @ApiParam(value = "用户ID", required = true, example = "1") @RequestParam Long userId,
            @ApiParam(value = "会话名称", required = false, example = "数学练习") @RequestParam(required = false) String sessionName,
            @ApiParam(value = "题目图片文件", required = true) @RequestParam("imageFile") MultipartFile imageFile,
            @ApiParam(value = "是否启用语音播报", required = false) @RequestParam(defaultValue = "false") Boolean enableVoice) {

        Map<String, Object> result = new HashMap<>();
        long startTime = System.currentTimeMillis();

        try {
            log.info("🔍 收到一体化搜题请求 - 用户ID: {}, 会话: {}, 文件: {}, 大小: {}KB, 语音播报: {}",
                userId, sessionName, imageFile.getOriginalFilename(), imageFile.getSize() / 1024, enableVoice);

            // 1. 参数验证
            if (userId == null || imageFile == null || imageFile.isEmpty()) {
                result.put("success", false);
                result.put("message", "参数错误：用户ID和图片文件不能为空");
                return result;
            }

            // 2. 计算图片哈希值，检查是否已处理过
            String imageHash = ImageHashUtil.calculateHash(imageFile.getBytes());
            log.info("📊 图片哈希值: {}", imageHash);

            // 检查缓存
            TutorQuestion cachedQuestion = tutorQuestionMapper.getQuestionByImageHash(imageHash);
            if (cachedQuestion != null) {
                log.info("💾 发现缓存题目，直接返回结果");
                return buildCachedResult(cachedQuestion, userId, sessionName);
            }

            // 3. OCR识别文字和公式
            log.info("🔤 开始OCR识别...");
            String ocrResult = aliyunOcrUtil.recognizeTextByStream(
                imageFile.getInputStream(),
                imageFile.getOriginalFilename()
            );

            JSONObject ocrJson = JSON.parseObject(ocrResult);
            String ocrText = extractTextFromOcrResult(ocrJson);
            String ocrLatex = extractLatexFromOcrResult(ocrJson);

            log.info("📝 OCR识别完成 - 文字长度: {}, LaTeX长度: {}", ocrText.length(),
                ocrLatex != null ? ocrLatex.length() : 0);

            // 4. 上传图片到MinIO
            log.info("📁 开始上传图片到MinIO...");
            String imageUrl = null;
            try {
                imageUrl = minioFileService.uploadQuestionImage(imageFile);
            } catch (Exception e) {
                log.warn("📁 图片上传失败，继续处理: {}", e.getMessage());
            }

            // 5. AI智能分析题目
            log.info("🤖 开始AI智能分析...");
            Map<String, Object> aiAnalysisResult = performComprehensiveAnalysis(ocrText, ocrLatex);

            // 6. 创建或获取会话
            TutorSession session = createOrGetSession(userId, sessionName);

            // 7. 保存题目记录到数据库
            TutorQuestion question = createTutorQuestion(userId, session.getId(), imageUrl, imageHash,
                ocrText, ocrLatex, aiAnalysisResult);
            tutorQuestionMapper.insert(question);

            // 8. 生成三道相似题目
            log.info("🎯 生成相似题目...");
            List<Map<String, Object>> similarQuestions = generateThreeSimilarQuestions(ocrText, aiAnalysisResult);

            // 9. 语音播报处理（先生成语音）
            String voiceFilePath = null;
            if (enableVoice && aiAnalysisResult.containsKey("answer")) {
                try {
                    String aiAnswer = (String) aiAnalysisResult.get("answer");
                    if (aiAnswer != null && !aiAnswer.trim().isEmpty()) {
                        log.info("🔊 开始生成搜题结果语音播报...");
                        voiceFilePath = generateVoiceForResponse(aiAnswer);
                        log.info("✅ 搜题语音播报文件生成成功: {}", voiceFilePath);
                    }
                } catch (Exception voiceError) {
                    log.warn("⚠️ 搜题语音播报生成失败，但不影响搜题: {}", voiceError.getMessage());
                }
            }

            // 10. 创建初始对话消息（包含语音文件）
            createInitialChatMessages(session.getId(), userId, question, aiAnalysisResult, voiceFilePath);

            // 11. 构建完整响应
            result = buildIntegratedResult(question, session, aiAnalysisResult, similarQuestions,
                System.currentTimeMillis() - startTime);

            // 添加语音播报相关信息
            result.put("voiceEnabled", enableVoice);
            if (voiceFilePath != null) {
                result.put("voiceFilePath", voiceFilePath);
                result.put("voiceGenerated", true);
            } else {
                result.put("voiceGenerated", false);
            }

            log.info("✅ 一体化搜题完成 - 题目ID: {}, 会话ID: {}, 耗时: {}ms",
                question.getId(), session.getId(), System.currentTimeMillis() - startTime);

        } catch (Exception e) {
            log.error("❌ 一体化搜题处理失败", e);
            result.put("success", false);
            result.put("message", "搜题失败: " + e.getMessage());
            result.put("error", e.getClass().getSimpleName());
            result.put("processingTime", System.currentTimeMillis() - startTime);
        }

        return result;
    }

    /**
     * 基于搜题结果继续对话（支持语音播报）
     */
    @PostMapping("/continue-conversation")
    @ApiOperation(value = "继续对话", notes = "基于搜题结果继续与AI对话，支持语音播报")
    public Map<String, Object> continueConversation(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "会话ID", required = true) @RequestParam Long sessionId,
            @ApiParam(value = "用户消息", required = true) @RequestParam String message,
            @ApiParam(value = "是否启用语音播报", required = false) @RequestParam(defaultValue = "false") Boolean enableVoice) {

        Map<String, Object> result = new HashMap<>();
        long startTime = System.currentTimeMillis();

        try {
            log.info("💬 继续对话 - 用户ID: {}, 会话ID: {}, 消息: {}, 语音播报: {}", userId, sessionId, message, enableVoice);

            // 1. 验证会话是否存在
            TutorSession session = tutorSessionMapper.selectById(sessionId);
            if (session == null || !session.getUserId().equals(userId)) {
                result.put("success", false);
                result.put("message", "会话不存在或无权限访问");
                return result;
            }

            // 2. 获取对话历史
            List<TutorMessage> conversationHistory = tutorMessageMapper.getFullConversationBySessionId(sessionId);

            // 3. 保存用户消息
            TutorMessage userMessage = new TutorMessage()
                .setSessionId(sessionId)
                .setUserId(userId)
                .setMessageType(TutorMessage.MESSAGE_TYPE_USER)
                .setContent(message)
                .setContentType(TutorMessage.CONTENT_TYPE_TEXT)
                .setCreatedTime(LocalDateTime.now())
                .setUpdatedTime(LocalDateTime.now());
            tutorMessageMapper.insert(userMessage);

            // 4. 构建对话上下文
            String conversationContext = buildConversationContext(conversationHistory, message);

            // 5. 获取AI回复
            String aiResponse = aiChatService.chatWithContext(conversationContext);

            // 6. 保存AI回复（先保存以获取ID）
            TutorMessage aiMessage = new TutorMessage()
                .setSessionId(sessionId)
                .setUserId(userId)
                .setMessageType(TutorMessage.MESSAGE_TYPE_AI)
                .setContent(aiResponse)
                .setContentType(TutorMessage.CONTENT_TYPE_TEXT)
                .setParentMessageId(userMessage.getId())
                .setCreatedTime(LocalDateTime.now())
                .setUpdatedTime(LocalDateTime.now());
            tutorMessageMapper.insert(aiMessage);

            // 7. 语音播报处理（关联到消息）
            String voiceFilePath = null;
            if (enableVoice && aiResponse != null && !aiResponse.trim().isEmpty()) {
                try {
                    log.info("🔊 开始生成对话语音播报...");
                    voiceFilePath = generateVoiceForResponse(aiResponse, aiMessage.getId());
                    log.info("✅ 对话语音播报文件生成成功: {}", voiceFilePath);
                } catch (Exception voiceError) {
                    log.warn("⚠️ 对话语音播报生成失败，但不影响对话: {}", voiceError.getMessage());
                }
            }

            // 8. 更新会话最后消息时间
            tutorSessionMapper.updateLastMessageTime(sessionId, LocalDateTime.now());

            result.put("success", true);
            result.put("message", "对话成功");
            result.put("userMessage", userMessage);
            result.put("aiResponse", aiMessage);
            result.put("sessionId", sessionId);
            result.put("processingTime", System.currentTimeMillis() - startTime);
            result.put("voiceEnabled", enableVoice);

            if (voiceFilePath != null) {
                result.put("voiceFilePath", voiceFilePath);
                result.put("voiceGenerated", true);
            } else {
                result.put("voiceGenerated", false);
            }

            log.info("✅ 对话完成 - 会话ID: {}, 耗时: {}ms", sessionId, System.currentTimeMillis() - startTime);

        } catch (Exception e) {
            log.error("❌ 对话处理失败", e);
            result.put("success", false);
            result.put("message", "对话失败: " + e.getMessage());
            result.put("processingTime", System.currentTimeMillis() - startTime);
        }

        return result;
    }

    // ==================== 会话管理API ====================

    /**
     * 获取用户会话列表
     */
    @GetMapping("/sessions")
    @ApiOperation(value = "获取用户会话列表", notes = "获取指定用户的最近会话")
    public Map<String, Object> getUserSessions(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "限制数量", required = false) @RequestParam(defaultValue = "10") Integer limit) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("📋 获取用户会话列表 - 用户ID: {}, 限制数量: {}", userId, limit);

            // 从Redis获取会话列表
            List<Map<String, Object>> sessions = getSessionsFromRedis(userId);

            // 如果Redis中没有数据，从数据库加载
            if (sessions.isEmpty()) {
                List<TutorSession> dbSessions = tutorSessionMapper.getActiveSessionsByUserId(userId);
                sessions = convertSessionsToRedisFormat(dbSessions);

                // 保存到Redis
                saveSessionsToRedis(userId, sessions);
            }

            // 限制返回数量，只返回最近的会话
            if (sessions.size() > limit) {
                sessions = sessions.subList(0, limit);
            }

            result.put("success", true);
            result.put("message", "获取会话列表成功");
            result.put("data", Map.of(
                "sessions", sessions,
                "total", sessions.size()
            ));

            log.info("✅ 获取会话列表成功 - 用户ID: {}, 会话数量: {}", userId, sessions.size());

        } catch (Exception e) {
            log.error("❌ 获取会话列表失败 - 用户ID: {}", userId, e);
            result.put("success", false);
            result.put("message", "获取会话列表失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 创建新会话
     */
    @PostMapping("/sessions")
    @ApiOperation(value = "创建新会话", notes = "为用户创建一个新的对话会话")
    public Map<String, Object> createSession(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "会话标题", required = false) @RequestParam(required = false) String title) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("➕ 创建新会话 - 用户ID: {}, 标题: {}", userId, title);

            // 生成会话ID
            String sessionId = generateSessionId();

            // 如果没有提供标题，生成默认标题
            if (title == null || title.trim().isEmpty()) {
                title = "会话 " + LocalDateTime.now().format(
                    DateTimeFormatter.ofPattern("MM-dd HH:mm"));
            }

            // 创建会话对象
            Map<String, Object> session = new HashMap<>();
            session.put("id", sessionId);
            session.put("title", title);
            session.put("userId", userId);
            session.put("createTime", LocalDateTime.now().toString());
            session.put("updateTime", LocalDateTime.now().toString());
            session.put("messageCount", 0);
            session.put("status", "ACTIVE");

            // 保存到Redis
            saveSessionToRedis(userId, session);

            // 同时保存到数据库作为备份
            TutorSession dbSession = new TutorSession()
                .setUserId(userId)
                .setSessionName(title)
                .setSessionType("CHAT")
                .setStatus("ACTIVE")
                .setCreatedTime(LocalDateTime.now())
                .setUpdatedTime(LocalDateTime.now())
                .setLastMessageTime(LocalDateTime.now());

            tutorSessionMapper.insert(dbSession);

            result.put("success", true);
            result.put("message", "会话创建成功");
            result.put("data", Map.of("session", session));

            log.info("✅ 会话创建成功 - 用户ID: {}, 会话ID: {}", userId, sessionId);

        } catch (Exception e) {
            log.error("❌ 创建会话失败 - 用户ID: {}", userId, e);
            result.put("success", false);
            result.put("message", "创建会话失败: " + e.getMessage());
        }

        return result;
    }



    /**
     * 构建缓存结果
     */
    private Map<String, Object> buildCachedResult(TutorQuestion cachedQuestion, Long userId, String sessionName) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 创建或获取会话
            TutorSession session = createOrGetSession(userId, sessionName);

            // 构建AI分析结果
            Map<String, Object> aiAnalysisResult = new HashMap<>();
            aiAnalysisResult.put("subject", cachedQuestion.getSubject());
            aiAnalysisResult.put("questionType", cachedQuestion.getQuestionType());
            aiAnalysisResult.put("analysis", cachedQuestion.getAiAnalysis());
            aiAnalysisResult.put("solution", cachedQuestion.getSolutionSteps());
            aiAnalysisResult.put("answer", cachedQuestion.getFinalAnswer());
            aiAnalysisResult.put("confidence", cachedQuestion.getConfidenceScore());

            // 生成相似题目
            List<Map<String, Object>> similarQuestions = generateThreeSimilarQuestions(
                cachedQuestion.getOcrText(), aiAnalysisResult);

            result.put("success", true);
            result.put("message", "搜题成功（来自缓存）");
            result.put("cached", true);
            result.put("questionId", cachedQuestion.getId());
            result.put("sessionId", session.getId());
            result.put("ocrText", cachedQuestion.getOcrText());
            result.put("analysis", aiAnalysisResult);
            result.put("similarQuestions", similarQuestions);
            result.put("processingTime", 50); // 缓存响应很快

        } catch (Exception e) {
            log.error("构建缓存结果失败", e);
            result.put("success", false);
            result.put("message", "缓存结果处理失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 从OCR结果中提取LaTeX公式
     */
    private String extractLatexFromOcrResult(JSONObject ocrJson) {
        try {
            if (ocrJson != null && ocrJson.containsKey("latex")) {
                return ocrJson.getString("latex");
            }
            // 如果没有专门的LaTeX字段，尝试从文本中提取数学公式
            return null;
        } catch (Exception e) {
            log.warn("提取LaTeX失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 执行综合AI分析
     */
    private Map<String, Object> performComprehensiveAnalysis(String ocrText, String ocrLatex) {
        Map<String, Object> analysisResult = new HashMap<>();

        try {
            // 1. 学科分类
            String subject = aiChatService.classifySubject(ocrText);

            // 2. 题型识别
            String questionType = aiChatService.identifyQuestionType(ocrText);

            // 3. 知识点提取
            String knowledgePoints = aiChatService.extractKnowledgePoints(ocrText);

            // 4. 难度评估
            Integer difficultyLevel = aiChatService.assessDifficulty(ocrText);

            // 5. 详细分析
            String detailedAnalysis = aiChatService.analyzeQuestion(ocrText);

            // 6. 解题步骤
            String solutionSteps = aiChatService.generateSolutionSteps(ocrText);

            // 7. 最终答案
            String finalAnswer = aiChatService.generateFinalAnswer(ocrText);

            // 8. 置信度评估
            BigDecimal confidence = aiChatService.calculateConfidence(ocrText, finalAnswer);

            analysisResult.put("subject", subject);
            analysisResult.put("questionType", questionType);
            analysisResult.put("knowledgePoints", knowledgePoints);
            analysisResult.put("difficultyLevel", difficultyLevel);
            analysisResult.put("analysis", detailedAnalysis);
            analysisResult.put("solutionSteps", solutionSteps);
            analysisResult.put("finalAnswer", finalAnswer);
            analysisResult.put("confidence", confidence);

            log.info("AI分析完成 - 学科: {}, 题型: {}, 难度: {}, 置信度: {}",
                subject, questionType, difficultyLevel, confidence);

        } catch (Exception e) {
            log.error("AI综合分析失败", e);
            // 提供默认值
            analysisResult.put("subject", "未知");
            analysisResult.put("questionType", "未知");
            analysisResult.put("analysis", "AI分析暂时不可用");
            analysisResult.put("solutionSteps", "请稍后重试");
            analysisResult.put("finalAnswer", "暂无答案");
            analysisResult.put("confidence", BigDecimal.valueOf(0.5));
        }

        return analysisResult;
    }

    /**
     * 创建或获取会话
     */
    private TutorSession createOrGetSession(Long userId, String sessionName) {
        try {
            // 如果没有提供会话名称，生成默认名称
            if (sessionName == null || sessionName.trim().isEmpty()) {
                sessionName = "搜题会话_" + LocalDateTime.now().format(
                    java.time.format.DateTimeFormatter.ofPattern("MMdd_HHmm"));
            }

            // 查找现有会话
            TutorSession existingSession = tutorSessionMapper.findByUserIdAndSessionName(userId, sessionName);
            if (existingSession != null) {
                log.info("找到现有会话: {}", existingSession.getId());
                return existingSession;
            }

            // 创建新会话
            TutorSession newSession = new TutorSession()
                .setUserId(userId)
                .setSessionName(sessionName)
                .setSessionType("QUESTION_SEARCH")
                .setStatus("ACTIVE")
                .setCreatedTime(LocalDateTime.now())
                .setUpdatedTime(LocalDateTime.now())
                .setLastMessageTime(LocalDateTime.now());

            tutorSessionMapper.insert(newSession);
            log.info("创建新会话: {}", newSession.getId());

            return newSession;

        } catch (Exception e) {
            log.error("创建或获取会话失败", e);
            throw new RuntimeException("会话处理失败: " + e.getMessage());
        }
    }

    /**
     * 创建题目记录
     */
    private TutorQuestion createTutorQuestion(Long userId, Long sessionId, String imageUrl,
            String imageHash, String ocrText, String ocrLatex, Map<String, Object> aiAnalysisResult) {

        // 安全提取和截断字段值
        String subject = extractSubject((String) aiAnalysisResult.get("subject"));
        String questionType = extractQuestionType((String) aiAnalysisResult.get("questionType"));
        String knowledgePoints = truncateString((String) aiAnalysisResult.get("knowledgePoints"), 200);
        String analysis = truncateString((String) aiAnalysisResult.get("analysis"), 1000);
        String solutionSteps = truncateString((String) aiAnalysisResult.get("solutionSteps"), 2000);
        String finalAnswer = truncateString((String) aiAnalysisResult.get("finalAnswer"), 500);

        log.info("📝 字段提取结果 - 学科: {}, 题型: {}", subject, questionType);

        TutorQuestion question = new TutorQuestion()
            .setUserId(userId)
            .setSessionId(sessionId)
            .setImageUrl(imageUrl)
            .setImageHash(imageHash)
            .setOcrText(ocrText)
            .setOcrLatex(ocrLatex)
            .setSubject(subject)
            .setQuestionType(questionType)
            .setKnowledgePoints(knowledgePoints)
            .setDifficultyLevel((Integer) aiAnalysisResult.get("difficultyLevel"))
            .setAiAnalysis(analysis)
            .setSolutionSteps(solutionSteps)
            .setFinalAnswer(finalAnswer)
            .setConfidenceScore((BigDecimal) aiAnalysisResult.get("confidence"))
            .setProcessingTime(100) // 将在调用处设置实际值
            .setModelVersion("qwen-vl-plus-v1.0")
            .setIsWrong(false)
            .setMasteryStatus(0)
            .setReviewCount(0)
            .setCreatedTime(LocalDateTime.now())
            .setUpdatedTime(LocalDateTime.now());

        return question;
    }

    /**
     * 生成三道相似题目（完全基于AI生成，不查询数据库）
     */
    private List<Map<String, Object>> generateThreeSimilarQuestions(String originalText, Map<String, Object> analysisResult) {
        List<Map<String, Object>> similarQuestions = new ArrayList<>();

        try {
            log.info("🎯 开始AI生成相似题目...");

            // 构建更详细的AI提示词
            String prompt = buildEnhancedSimilarQuestionPrompt(originalText, analysisResult);

            // 调用AI生成相似题目
            String aiResponse = aiChatService.generateSimilarQuestions(prompt, 3);
            log.info("🤖 AI返回的相似题目: {}", aiResponse);

            // 解析AI返回的JSON
            try {
                List<Map<String, Object>> aiGeneratedQuestions = safeParseJsonArray(aiResponse);

                // 处理AI生成的题目
                for (int i = 0; i < Math.min(3, aiGeneratedQuestions.size()); i++) {
                    Map<String, Object> question = aiGeneratedQuestions.get(i);

                    // 添加元数据
                    question.put("questionId", "ai_similar_" + System.currentTimeMillis() + "_" + (i + 1));
                    question.put("difficulty", analysisResult.get("difficultyLevel"));
                    question.put("subject", analysisResult.get("subject"));
                    question.put("questionType", analysisResult.get("questionType"));
                    question.put("generatedBy", "AI");
                    question.put("generatedTime", LocalDateTime.now());
                    question.put("originalQuestionHash", originalText.hashCode());

                    similarQuestions.add(question);
                }

                log.info("✅ AI成功生成{}道相似题目", similarQuestions.size());

            } catch (Exception parseError) {
                log.warn("⚠️ 解析AI生成的相似题目失败，使用智能备用方案: {}", parseError.getMessage());
                similarQuestions = generateIntelligentFallbackQuestions(originalText, analysisResult);
            }

        } catch (Exception e) {
            log.error("❌ AI生成相似题目失败，使用智能备用方案", e);
            similarQuestions = generateIntelligentFallbackQuestions(originalText, analysisResult);
        }

        log.info("✅ 相似题目生成完成，共{}道（全部为AI生成，无数据库查询）", similarQuestions.size());
        return similarQuestions;
    }

    /**
     * 构建增强版相似题目生成提示词
     */
    private String buildEnhancedSimilarQuestionPrompt(String originalText, Map<String, Object> analysisResult) {
        return String.format("""
            你是一位专业的教育专家，请基于以下题目信息，创造性地生成3道相似但不重复的题目：

            【原题目】
            %s

            【题目分析】
            - 学科：%s
            - 题型：%s
            - 难度等级：%s/5
            - 知识点：%s

            【生成要求】
            1. 保持相同的学科、题型和难度等级
            2. 改变具体的数值、条件或情境，但保持核心知识点
            3. 确保每道题目都有独特性，避免简单的数字替换
            4. 题目要有实际教育价值和应用意义
            5. 提供完整的解答过程和思路

            【输出格式】
            请严格按照以下JSON数组格式返回，不要包含任何其他文字：
            [
              {
                "question": "第一道题目的完整描述",
                "answer": "第一道题目的最终答案",
                "explanation": "第一道题目的详细解题步骤和思路"
              },
              {
                "question": "第二道题目的完整描述",
                "answer": "第二道题目的最终答案",
                "explanation": "第二道题目的详细解题步骤和思路"
              },
              {
                "question": "第三道题目的完整描述",
                "answer": "第三道题目的最终答案",
                "explanation": "第三道题目的详细解题步骤和思路"
              }
            ]
            """,
            originalText,
            analysisResult.get("subject"),
            analysisResult.get("questionType"),
            analysisResult.get("difficultyLevel"),
            analysisResult.get("knowledgePoints")
        );
    }

    /**
     * 生成智能备用相似题目（当AI解析失败时使用）
     */
    private List<Map<String, Object>> generateIntelligentFallbackQuestions(String originalText, Map<String, Object> analysisResult) {
        List<Map<String, Object>> fallbackQuestions = new ArrayList<>();

        String subject = (String) analysisResult.get("subject");
        String questionType = (String) analysisResult.get("questionType");
        Integer difficulty = (Integer) analysisResult.get("difficultyLevel");

        log.info("🔄 使用智能备用方案生成相似题目 - 学科: {}, 题型: {}, 难度: {}", subject, questionType, difficulty);

        try {
            // 尝试使用简化的AI提示词重新生成
            String simplifiedPrompt = String.format("""
                基于题目"%s"，生成3道%s学科的%s类型题目。
                要求：
                1. 难度等级%d/5
                2. 改变数值但保持题型
                3. 只返回JSON数组：[{"question":"题目","answer":"答案","explanation":"解释"}]
                """,
                originalText.length() > 100 ? originalText.substring(0, 100) + "..." : originalText,
                subject, questionType, difficulty);

            String aiResponse = aiChatService.generateSimilarQuestions(simplifiedPrompt, 3);
            log.info("🤖 智能备用方案AI响应: {}", aiResponse);

            // 安全解析JSON
            List<Map<String, Object>> aiQuestions = safeParseJsonArray(aiResponse);

            for (int i = 0; i < Math.min(3, aiQuestions.size()); i++) {
                Map<String, Object> question = aiQuestions.get(i);
                question.put("questionId", "fallback_ai_" + System.currentTimeMillis() + "_" + (i + 1));
                question.put("difficulty", difficulty);
                question.put("subject", subject);
                question.put("generatedBy", "AI_FALLBACK");
                fallbackQuestions.add(question);
            }

            log.info("✅ 智能备用方案成功生成{}道题目", fallbackQuestions.size());

        } catch (Exception e) {
            log.warn("⚠️ 智能备用方案也失败，使用模板生成", e);
            fallbackQuestions = generateTemplateFallbackQuestions(originalText, analysisResult);
        }

        return fallbackQuestions;
    }

    /**
     * 生成模板备用相似题目（最后的备用方案）
     */
    private List<Map<String, Object>> generateTemplateFallbackQuestions(String originalText, Map<String, Object> analysisResult) {
        List<Map<String, Object>> templateQuestions = new ArrayList<>();

        String subject = (String) analysisResult.get("subject");
        Integer difficulty = (Integer) analysisResult.get("difficultyLevel");

        for (int i = 1; i <= 3; i++) {
            Map<String, Object> question = new HashMap<>();
            question.put("questionId", "template_" + System.currentTimeMillis() + "_" + i);
            question.put("question", generateTemplateQuestion(originalText, subject, i));
            question.put("answer", "请根据题目要求进行计算和分析");
            question.put("explanation", String.format("这是一道%s相关的练习题，请运用相同的知识点和解题方法进行求解", subject));
            question.put("difficulty", difficulty);
            question.put("subject", subject);
            question.put("generatedBy", "TEMPLATE");
            question.put("generatedTime", LocalDateTime.now());

            templateQuestions.add(question);
        }

        log.info("📝 模板备用方案生成{}道题目", templateQuestions.size());
        return templateQuestions;
    }

    /**
     * 生成模板题目内容
     */
    private String generateTemplateQuestion(String originalText, String subject, int index) {
        if (originalText == null || originalText.trim().isEmpty()) {
            return String.format("这是一道%s练习题 %d", subject, index);
        }

        // 基于原题目生成变化
        String[] templates = {
            "参考题目：" + (originalText.length() > 50 ? originalText.substring(0, 50) + "..." : originalText),
            "类似问题：请运用相同方法解决类似的" + subject + "问题",
            "举一反三：基于上述题目，请思考相关的" + subject + "应用"
        };

        return templates[(index - 1) % templates.length];
    }

    /**
     * 安全截断字符串，防止数据库字段长度超限
     */
    private String truncateString(String str, int maxLength) {
        if (str == null) {
            return null;
        }

        // 移除可能的格式标记和多余空白
        String cleaned = str.trim()
            .replaceAll("【[^】]*】[：:]?", "") // 移除【标题】：格式
            .replaceAll("\\*\\*([^*]+)\\*\\*", "$1") // 移除**粗体**格式
            .replaceAll("\\n+", " ") // 将换行符替换为空格
            .replaceAll("\\s+", " ") // 合并多个空格
            .trim();

        if (cleaned.length() <= maxLength) {
            return cleaned;
        }

        // 截断并添加省略号
        return cleaned.substring(0, maxLength - 3) + "...";
    }

    /**
     * 智能提取简洁的题型信息
     */
    private String extractQuestionType(String rawQuestionType) {
        if (rawQuestionType == null || rawQuestionType.trim().isEmpty()) {
            return "未知题型";
        }

        String cleaned = rawQuestionType.trim();

        // 常见题型关键词
        String[] questionTypes = {
            "选择题", "填空题", "计算题", "证明题", "应用题", "解答题",
            "判断题", "简答题", "分析题", "综合题", "实验题", "作图题"
        };

        // 查找匹配的题型
        for (String type : questionTypes) {
            if (cleaned.contains(type)) {
                return type;
            }
        }

        // 如果没有找到标准题型，提取第一个有意义的词
        String[] words = cleaned.split("[\\s，,。.：:]");
        for (String word : words) {
            word = word.trim();
            if (word.length() >= 2 && word.length() <= 10 && !word.matches(".*[【】\\[\\]].*")) {
                return word;
            }
        }

        // 最后的备用方案
        return truncateString(cleaned, 20);
    }

    /**
     * 智能提取学科信息
     */
    private String extractSubject(String rawSubject) {
        if (rawSubject == null || rawSubject.trim().isEmpty()) {
            return "未知";
        }

        String cleaned = rawSubject.trim();

        // 常见学科关键词
        String[] subjects = {
            "数学", "语文", "英语", "物理", "化学", "生物",
            "历史", "地理", "政治", "科学", "计算机"
        };

        // 查找匹配的学科
        for (String subject : subjects) {
            if (cleaned.contains(subject)) {
                return subject;
            }
        }

        // 如果没有找到标准学科，返回截断的原始内容
        return truncateString(cleaned, 20);
    }

    /**
     * 提取和清理JSON内容
     */
    private String extractAndCleanJson(String aiResponse) {
        if (aiResponse == null || aiResponse.trim().isEmpty()) {
            return "[]";
        }

        try {
            // 移除可能的前后缀文本，只保留JSON部分
            String cleaned = aiResponse.trim();

            // 查找JSON数组的开始和结束
            int startIndex = cleaned.indexOf('[');
            int endIndex = cleaned.lastIndexOf(']');

            if (startIndex != -1 && endIndex != -1 && endIndex > startIndex) {
                cleaned = cleaned.substring(startIndex, endIndex + 1);
            } else {
                // 如果没有找到数组，查找JSON对象
                startIndex = cleaned.indexOf('{');
                endIndex = cleaned.lastIndexOf('}');

                if (startIndex != -1 && endIndex != -1 && endIndex > startIndex) {
                    // 将单个对象包装成数组
                    cleaned = "[" + cleaned.substring(startIndex, endIndex + 1) + "]";
                } else {
                    log.warn("⚠️ 无法从AI响应中提取有效JSON，返回空数组");
                    return "[]";
                }
            }

            // 清理常见的JSON格式问题
            cleaned = cleaned
                .replaceAll("```json", "")
                .replaceAll("```", "")
                .replaceAll("\\n", "")
                .replaceAll("\\r", "")
                .trim();

            // 验证JSON格式
            JSON.parseArray(cleaned);

            return cleaned;

        } catch (Exception e) {
            log.warn("⚠️ JSON清理失败: {}", e.getMessage());
            return "[]";
        }
    }

    /**
     * 安全的JSON解析方法
     */
    private List<Map<String, Object>> safeParseJsonArray(String jsonString) {
        List<Map<String, Object>> result = new ArrayList<>();

        try {
            if (jsonString == null || jsonString.trim().isEmpty()) {
                return result;
            }

            String cleanedJson = extractAndCleanJson(jsonString);

            @SuppressWarnings("unchecked")
            List<Map<String, Object>> parsed = JSON.parseArray(cleanedJson)
                .stream()
                .map(obj -> (Map<String, Object>) obj)
                .collect(Collectors.toList());

            return parsed;

        } catch (Exception e) {
            log.warn("⚠️ JSON解析失败: {}, 原始内容: {}", e.getMessage(), jsonString);
            return result;
        }
    }

    /**
     * 生成默认相似题目（当AI生成失败时使用）
     */
    private List<Map<String, Object>> generateDefaultSimilarQuestions(String originalText, Map<String, Object> analysisResult) {
        List<Map<String, Object>> defaultQuestions = new ArrayList<>();

        String subject = (String) analysisResult.get("subject");

        if ("数学".equals(subject)) {
            defaultQuestions.add(createDefaultMathQuestion(1));
            defaultQuestions.add(createDefaultMathQuestion(2));
            defaultQuestions.add(createDefaultMathQuestion(3));
        } else if ("物理".equals(subject)) {
            defaultQuestions.add(createDefaultPhysicsQuestion(1));
            defaultQuestions.add(createDefaultPhysicsQuestion(2));
            defaultQuestions.add(createDefaultPhysicsQuestion(3));
        } else {
            // 通用题目
            defaultQuestions.add(createDefaultGenericQuestion(1, subject));
            defaultQuestions.add(createDefaultGenericQuestion(2, subject));
            defaultQuestions.add(createDefaultGenericQuestion(3, subject));
        }

        return defaultQuestions;
    }

    /**
     * 创建默认数学题目
     */
    private Map<String, Object> createDefaultMathQuestion(int index) {
        Map<String, Object> question = new HashMap<>();
        switch (index) {
            case 1:
                question.put("question", "求解方程：3x + 5 = 14");
                question.put("answer", "x = 3");
                question.put("explanation", "移项得：3x = 14 - 5 = 9，所以 x = 9 ÷ 3 = 3");
                break;
            case 2:
                question.put("question", "计算：(2x + 1)(x - 3) = 0 的解");
                question.put("answer", "x = -1/2 或 x = 3");
                question.put("explanation", "根据零乘积性质，2x + 1 = 0 或 x - 3 = 0");
                break;
            case 3:
                question.put("question", "已知函数 f(x) = 2x + 1，求 f(3) 的值");
                question.put("answer", "f(3) = 7");
                question.put("explanation", "将 x = 3 代入函数：f(3) = 2×3 + 1 = 7");
                break;
        }
        question.put("questionId", "default_math_" + index);
        question.put("subject", "数学");
        return question;
    }

    /**
     * 创建默认物理题目
     */
    private Map<String, Object> createDefaultPhysicsQuestion(int index) {
        Map<String, Object> question = new HashMap<>();
        switch (index) {
            case 1:
                question.put("question", "一个物体从静止开始，以2m/s²的加速度运动，求3秒后的速度");
                question.put("answer", "v = 6 m/s");
                question.put("explanation", "根据公式 v = v₀ + at，v = 0 + 2×3 = 6 m/s");
                break;
            case 2:
                question.put("question", "计算重力为10N的物体在地面上的质量");
                question.put("answer", "m = 1 kg");
                question.put("explanation", "根据 G = mg，m = G/g = 10/10 = 1 kg");
                break;
            case 3:
                question.put("question", "一个弹簧的弹性系数为100N/m，压缩0.1m时的弹力是多少？");
                question.put("answer", "F = 10 N");
                question.put("explanation", "根据胡克定律 F = kx，F = 100×0.1 = 10 N");
                break;
        }
        question.put("questionId", "default_physics_" + index);
        question.put("subject", "物理");
        return question;
    }

    /**
     * 创建默认通用题目
     */
    private Map<String, Object> createDefaultGenericQuestion(int index, String subject) {
        Map<String, Object> question = new HashMap<>();
        question.put("question", String.format("这是一道%s相关的练习题目 %d", subject, index));
        question.put("answer", "请参考教材相关章节");
        question.put("explanation", "建议复习相关知识点后再次尝试");
        question.put("questionId", "default_generic_" + index);
        question.put("subject", subject);
        return question;
    }

    /**
     * 创建初始对话消息
     */
    private void createInitialChatMessages(Long sessionId, Long userId, TutorQuestion question, Map<String, Object> analysisResult) {
        createInitialChatMessages(sessionId, userId, question, analysisResult, null);
    }

    /**
     * 创建初始对话消息（支持语音文件）
     */
    private void createInitialChatMessages(Long sessionId, Long userId, TutorQuestion question, Map<String, Object> analysisResult, String voiceFileUrl) {
        try {
            // 创建用户的初始消息（题目图片）
            TutorMessage userMessage = new TutorMessage()
                .setSessionId(sessionId)
                .setUserId(userId)
                .setMessageType(TutorMessage.MESSAGE_TYPE_USER)
                .setContent("我上传了一道题目，请帮我分析解答")
                .setContentType(TutorMessage.CONTENT_TYPE_IMAGE)
                .setMetadata(JSON.toJSONString(Map.of(
                    "imageUrl", question.getImageUrl(),
                    "ocrText", question.getOcrText()
                )))
                .setCreatedTime(LocalDateTime.now())
                .setUpdatedTime(LocalDateTime.now());
            tutorMessageMapper.insert(userMessage);

            // 创建AI的分析回复
            String aiResponse = buildInitialAiResponse(analysisResult);
            TutorMessage aiMessage = new TutorMessage()
                .setSessionId(sessionId)
                .setUserId(userId)
                .setMessageType(TutorMessage.MESSAGE_TYPE_AI)
                .setContent(aiResponse)
                .setContentType(TutorMessage.CONTENT_TYPE_TEXT)
                .setParentMessageId(userMessage.getId())
                .setCreatedTime(LocalDateTime.now())
                .setUpdatedTime(LocalDateTime.now());

            // 如果有语音文件，设置语音相关信息
            if (voiceFileUrl != null && !voiceFileUrl.trim().isEmpty()) {
                // 从URL中提取文件名
                String voiceFileName = extractFileNameFromUrl(voiceFileUrl);
                aiMessage.setVoiceFileUrl(voiceFileUrl)
                         .setVoiceFileName(voiceFileName)
                         .setVoiceDuration(estimateVoiceDuration(aiResponse));
            }

            tutorMessageMapper.insert(aiMessage);

            log.info("✅ 创建初始对话消息完成");

        } catch (Exception e) {
            log.error("创建初始对话消息失败", e);
        }
    }

    /**
     * 构建初始AI回复
     */
    private String buildInitialAiResponse(Map<String, Object> analysisResult) {
        StringBuilder response = new StringBuilder();
        response.append("我已经分析了您的题目，以下是详细解答：\n\n");

        response.append("📚 **学科分类**：").append(analysisResult.get("subject")).append("\n");
        response.append("🏷️ **题目类型**：").append(analysisResult.get("questionType")).append("\n");
        response.append("⭐ **难度等级**：").append(analysisResult.get("difficultyLevel")).append("/5\n\n");

        response.append("🔍 **题目分析**：\n").append(analysisResult.get("analysis")).append("\n\n");

        response.append("📝 **解题步骤**：\n").append(analysisResult.get("solutionSteps")).append("\n\n");

        response.append("✅ **最终答案**：").append(analysisResult.get("finalAnswer")).append("\n\n");

        response.append("💡 **小提示**：如果您对解题过程有任何疑问，可以继续提问，我会为您详细解释！");

        return response.toString();
    }

    /**
     * 构建完整的一体化结果
     */
    private Map<String, Object> buildIntegratedResult(TutorQuestion question, TutorSession session,
            Map<String, Object> analysisResult, List<Map<String, Object>> similarQuestions, long processingTime) {

        Map<String, Object> result = new HashMap<>();

        result.put("success", true);
        result.put("message", "一体化搜题完成");
        result.put("cached", false);

        // 基本信息
        result.put("questionId", question.getId());
        result.put("sessionId", session.getId());
        result.put("sessionName", session.getSessionName());

        // OCR结果
        result.put("ocrText", question.getOcrText());
        result.put("ocrLatex", question.getOcrLatex());
        result.put("imageUrl", question.getImageUrl());

        // AI分析结果
        result.put("analysis", analysisResult);

        // 相似题目
        result.put("similarQuestions", similarQuestions);

        // 对话功能提示
        result.put("chatEnabled", true);
        result.put("chatInstructions", "您可以使用 /continue-conversation 接口继续与AI对话");

        // 性能信息
        result.put("processingTime", processingTime);
        result.put("timestamp", System.currentTimeMillis());

        return result;
    }

    /**
     * 构建对话上下文
     */
    private String buildConversationContext(List<TutorMessage> conversationHistory, String newMessage) {
        StringBuilder context = new StringBuilder();
        context.append("以下是我们之前的对话历史：\n\n");

        for (TutorMessage message : conversationHistory) {
            if (TutorMessage.MESSAGE_TYPE_USER.equals(message.getMessageType())) {
                context.append("用户：").append(message.getContent()).append("\n");
            } else if (TutorMessage.MESSAGE_TYPE_AI.equals(message.getMessageType())) {
                context.append("AI：").append(message.getContent()).append("\n");
            }
        }

        context.append("\n现在用户的新问题是：").append(newMessage);
        context.append("\n\n请基于上述对话历史，回答用户的新问题。保持回答的连贯性和相关性。");

        return context.toString();
    }

    /**
     * 从OCR结果中提取文字
     */
    private String extractTextFromOcrResult(JSONObject ocrJson) {
        try {
            if (ocrJson == null) {
                return "";
            }

            // 尝试不同的OCR结果格式
            if (ocrJson.containsKey("words_result")) {
                // 百度OCR格式
                return ocrJson.getJSONArray("words_result")
                    .stream()
                    .map(item -> ((JSONObject) item).getString("words"))
                    .collect(Collectors.joining("\n"));
            } else if (ocrJson.containsKey("text")) {
                // 通用文本格式
                return ocrJson.getString("text");
            } else if (ocrJson.containsKey("content")) {
                // 阿里云OCR格式
                return ocrJson.getString("content");
            } else {
                // 直接返回JSON字符串
                return ocrJson.toString();
            }
        } catch (Exception e) {
            log.error("提取OCR文字失败", e);
            return "OCR识别失败";
        }
    }

    /**
     * 基于搜题结果继续对话
     */
    @PostMapping("/continue-chat")
    @ApiOperation(value = "基于搜题结果继续对话", notes = "在搜题结果基础上继续与AI对话")
    public Map<String, Object> continueChat(
            @RequestParam Long userId,
            @RequestParam Long questionId,
            @RequestParam String message) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("🔄 基于搜题结果继续对话 - 用户ID: {}, 题目ID: {}, 消息: {}", userId, questionId, message);

            // 获取题目信息
            QuestionRecord question = questionRecordMapper.selectById(questionId);
            if (question == null) {
                result.put("success", false);
                result.put("message", "题目不存在");
                return result;
            }

            // 构建包含题目信息的上下文
            String contextInfo = buildQuestionContext(question);
            String fullMessage = contextInfo + "\n\n用户问题：" + message + "\n\n" +
                "请基于上述题目信息，详细回答用户的问题。";

            // 调用AI服务获取回复
            String response = aiChatService.chat(fullMessage);

            // 如果用户询问相似题目，生成新的相似题目
            List<Map<String, Object>> newSimilarQuestions = new ArrayList<>();
            if (message.contains("相似") || message.contains("类似") || message.contains("举一反三")) {
                newSimilarQuestions = generateSimilarQuestions(question.getQuestionText());
            }

            result.put("success", true);
            result.put("message", "对话成功");
            result.put("data", Map.of(
                "questionId", questionId,
                "userMessage", message,
                "aiResponse", response,
                "questionInfo", buildQuestionResult(question),
                "newSimilarQuestions", newSimilarQuestions,
                "timestamp", System.currentTimeMillis()
            ));

            log.info("✅ 基于搜题结果的对话完成 - 用户ID: {}", userId);

        } catch (Exception e) {
            log.error("❌ 基于搜题结果的对话失败 - 用户ID: {}, 题目ID: {}", userId, questionId, e);
            result.put("success", false);
            result.put("message", "对话失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * OCR文字识别接口
     */
    @PostMapping("/ocr")
    @ApiOperation(value = "OCR文字识别", notes = "识别图片中的文字内容")
    public Map<String, Object> ocrRecognition(@RequestBody Map<String, Object> request) {
        long startTime = System.currentTimeMillis();
        Map<String, Object> result = new HashMap<>();

        try {
            log.info("🔍 收到OCR识别请求");

            String imageData = (String) request.get("imageData");
            if (imageData == null || imageData.trim().isEmpty()) {
                result.put("success", false);
                result.put("message", "图片数据不能为空");
                return result;
            }

            // 处理Base64图片数据
            String base64Data = imageData;
            if (imageData.startsWith("data:image")) {
                base64Data = imageData.substring(imageData.indexOf(",") + 1);
            }

            // 将Base64转换为字节数组
            byte[] imageBytes = Base64.getDecoder().decode(base64Data);

            // 调用OCR服务识别文字
            String recognizedText = aliyunOcrUtil.recognizeTextByStream(
                new java.io.ByteArrayInputStream(imageBytes), "ocr_image.jpg");

            if (recognizedText != null && !recognizedText.trim().isEmpty()) {
                result.put("success", true);
                result.put("message", "OCR识别成功");
                result.put("data", Map.of(
                    "text", recognizedText.trim(),
                    "confidence", 0.95, // 模拟置信度
                    "processingTime", System.currentTimeMillis() - startTime
                ));

                log.info("✅ OCR识别成功 - 识别文字长度: {}, 耗时: {}ms",
                    recognizedText.length(), System.currentTimeMillis() - startTime);
            } else {
                result.put("success", false);
                result.put("message", "未识别到文字内容");
            }

        } catch (Exception e) {
            log.error("❌ OCR识别失败", e);
            result.put("success", false);
            result.put("message", "OCR识别失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 简单AI对话接口（无需用户ID）
     */
    @PostMapping("/chat")
    @ApiOperation(value = "简单AI对话", notes = "与AI进行简单对话，无需登录")
    public Map<String, Object> simpleChat(@RequestParam(required = false) String message, @RequestBody(required = false) Map<String, Object> requestBody) {
        long startTime = System.currentTimeMillis();
        Map<String, Object> result = new HashMap<>();

        try {
            String chatMessage = message;
            String imageData = null;

            // 如果是POST请求体，从body中获取数据
            if (requestBody != null) {
                chatMessage = (String) requestBody.get("message");
                imageData = (String) requestBody.get("imageData");
            }

            log.info("🤖 简单AI对话 - 消息: {}, 包含图片: {}", chatMessage, imageData != null);

            if ((chatMessage == null || chatMessage.trim().isEmpty()) && imageData == null) {
                result.put("success", false);
                result.put("message", "消息内容或图片数据不能为空");
                return result;
            }

            String response;

            // 如果包含图片，先进行OCR识别
            if (imageData != null) {
                try {
                    // 处理Base64图片数据
                    String base64Data = imageData;
                    if (imageData.startsWith("data:image")) {
                        base64Data = imageData.substring(imageData.indexOf(",") + 1);
                    }

                    // 将Base64转换为字节数组
                    byte[] imageBytes = Base64.getDecoder().decode(base64Data);

                    // 调用OCR服务识别文字
                    String ocrText = aliyunOcrUtil.recognizeTextByStream(
                        new java.io.ByteArrayInputStream(imageBytes), "chat_image.jpg");

                    // 构建包含图片分析的消息
                    String fullMessage = (chatMessage != null ? chatMessage + "\n\n" : "") +
                        "图片中识别的文字内容：\n" + (ocrText != null ? ocrText : "未识别到文字内容") +
                        "\n\n请基于图片内容和用户问题进行回答。";

                    response = aiChatService.chat(fullMessage);

                } catch (Exception ocrError) {
                    log.warn("OCR识别失败，仅处理文字消息: {}", ocrError.getMessage());
                    response = aiChatService.chat(chatMessage != null ? chatMessage.trim() : "请分析这张图片");
                }
            } else {
                // 纯文字对话
                response = aiChatService.chat(chatMessage.trim());
            }

            result.put("success", true);
            result.put("message", "对话成功");
            result.put("data", response);
            result.put("processingTime", System.currentTimeMillis() - startTime);

            log.info("✅ 简单AI对话成功 - 耗时: {}ms", System.currentTimeMillis() - startTime);

        } catch (Exception e) {
            log.error("❌ 简单AI对话失败", e);
            result.put("success", false);
            result.put("message", "对话失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * AI对话接口 - 支持前端会话ID（支持语音播报和上下文）
     */
    @PostMapping("/chat-with-session")
    @ApiOperation(value = "AI对话", notes = "与AI进行自然语言对话，支持前端会话ID和上下文理解")
    public Map<String, Object> chatWithSession(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "前端会话ID", required = false) @RequestParam(required = false) String sessionId,
            @ApiParam(value = "用户消息", required = true) @RequestParam String message,
            @ApiParam(value = "是否启用语音播报", required = false) @RequestParam(defaultValue = "false") Boolean enableVoice) {

        long startTime = System.currentTimeMillis();

        try {
            log.info("💬 AI对话请求 - 用户ID: {}, 会话ID: {}, 消息长度: {}, 语音播报: {}",
                    userId, sessionId, message != null ? message.length() : 0, enableVoice);

            // 参数验证
            if (userId == null) {
                return buildErrorResponse("用户ID不能为空", "PARAM_ERROR");
            }

            if (message == null || message.trim().isEmpty()) {
                return buildErrorResponse("消息内容不能为空", "PARAM_ERROR");
            }

            if (message.length() > 1000) {
                return buildErrorResponse("消息长度不能超过1000字符", "MESSAGE_TOO_LONG");
            }

            // 如果没有会话ID，创建新会话
            if (sessionId == null || sessionId.trim().isEmpty()) {
                sessionId = generateSessionId();
                log.info("🆕 创建新会话ID: {}", sessionId);

                // 创建新会话并保存到Redis
                Map<String, Object> newSession = new HashMap<>();
                newSession.put("id", sessionId);
                newSession.put("title", "AI对话 " + LocalDateTime.now().format(
                    DateTimeFormatter.ofPattern("MM-dd HH:mm")));
                newSession.put("userId", userId);
                newSession.put("createTime", LocalDateTime.now().toString());
                newSession.put("updateTime", LocalDateTime.now().toString());
                newSession.put("messageCount", 0);
                newSession.put("status", "ACTIVE");

                saveSessionToRedis(userId, newSession);
            }

            // 构建上下文消息（从Redis获取历史消息）
            String contextMessage = message.trim();
            List<Map<String, Object>> historyMessages = getMessagesFromRedis(sessionId);

            if (!historyMessages.isEmpty()) {
                log.info("🔄 处理会话上下文 - 会话ID: {}, 历史消息数: {}", sessionId, historyMessages.size());
                contextMessage = buildContextMessageFromHistory(historyMessages, message.trim());
            }

            // 调用AI服务
            String response = aiChatService.chat(contextMessage);

            // 语音播报处理
            String voiceFilePath = null;
            if (enableVoice && response != null && !response.trim().isEmpty()) {
                try {
                    log.info("🔊 开始生成语音播报...");
                    voiceFilePath = generateVoiceForResponse(response);
                    log.info("✅ 语音播报文件生成成功: {}", voiceFilePath);
                } catch (Exception voiceError) {
                    log.warn("⚠️ 语音播报生成失败，但不影响对话: {}", voiceError.getMessage());
                }
            }

            // 保存对话记录到Redis
            saveMessageToRedis(userId, sessionId, message.trim(), response);

            // 构建成功响应
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("userMessage", message.trim());
            responseData.put("aiResponse", response);
            responseData.put("userId", userId);
            responseData.put("sessionId", sessionId);
            responseData.put("processingTime", System.currentTimeMillis() - startTime);
            responseData.put("voiceEnabled", enableVoice);

            if (voiceFilePath != null) {
                responseData.put("voiceFilePath", voiceFilePath);
                responseData.put("voiceGenerated", true);
            } else {
                responseData.put("voiceGenerated", false);
            }

            return buildSuccessResponse("对话成功", responseData);

        } catch (Exception e) {
            log.error("❌ AI对话失败 - 用户ID: {}, 会话ID: {}, 错误: {}", userId, sessionId, e.getMessage(), e);
            return buildErrorResponse("对话处理失败: " + e.getMessage(), "CHAT_ERROR");
        }
    }

    /**
     * AI对话接口 - 优化版（支持语音播报）
     */
    @PostMapping("/chat-with-user")
    @ApiOperation(value = "AI对话", notes = "与AI进行自然语言对话，支持上下文理解和语音播报")
    public Map<String, Object> chat(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "用户消息", required = true) @RequestParam String message,
            @ApiParam(value = "是否启用语音播报", required = false) @RequestParam(defaultValue = "false") Boolean enableVoice) {

        long startTime = System.currentTimeMillis();

        try {
            log.info("💬 AI对话请求 - 用户ID: {}, 消息长度: {}, 语音播报: {}", userId, message != null ? message.length() : 0, enableVoice);

            // 参数验证
            if (userId == null) {
                return buildErrorResponse("用户ID不能为空", "PARAM_ERROR");
            }

            if (message == null || message.trim().isEmpty()) {
                return buildErrorResponse("消息内容不能为空", "PARAM_ERROR");
            }

            if (message.length() > 1000) {
                return buildErrorResponse("消息长度不能超过1000字符", "MESSAGE_TOO_LONG");
            }

            // 调用AI服务
            String response = aiChatService.chat(message.trim());

            // 语音播报处理
            String voiceFilePath = null;
            if (enableVoice && response != null && !response.trim().isEmpty()) {
                try {
                    log.info("🔊 开始生成语音播报...");
                    voiceFilePath = generateVoiceForResponse(response);
                    log.info("✅ 语音播报文件生成成功: {}", voiceFilePath);
                } catch (Exception voiceError) {
                    log.warn("⚠️ 语音播报生成失败，但不影响对话: {}", voiceError.getMessage());
                }
            }

            // 构建成功响应
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("userMessage", message.trim());
            responseData.put("aiResponse", response);
            responseData.put("userId", userId);
            responseData.put("processingTime", System.currentTimeMillis() - startTime);
            responseData.put("voiceEnabled", enableVoice);

            if (voiceFilePath != null) {
                responseData.put("voiceFilePath", voiceFilePath);
                responseData.put("voiceGenerated", true);
            } else {
                responseData.put("voiceGenerated", false);
            }

            return buildSuccessResponse("对话成功", responseData);

        } catch (Exception e) {
            log.error("❌ AI对话失败 - 用户ID: {}, 错误: {}", userId, e.getMessage(), e);
            return buildErrorResponse("对话失败: " + e.getMessage(), "AI_CHAT_ERROR");
        }
    }



    /**
     * 获取会话详细信息和对话记录
     */
    @GetMapping("/session/{sessionId}/messages")
    @ApiOperation(value = "获取会话对话记录", notes = "获取指定会话的完整对话记录")
    public Map<String, Object> getSessionMessages(
            @ApiParam(value = "会话ID", required = true) @PathVariable Long sessionId,
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "页码", required = false) @RequestParam(defaultValue = "1") Integer page,
            @ApiParam(value = "每页数量", required = false) @RequestParam(defaultValue = "50") Integer size) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("💬 获取会话对话记录 - 会话ID: {}, 用户ID: {}", sessionId, userId);

            // 验证会话是否存在且属于该用户
            TutorSession session = tutorSessionMapper.selectById(sessionId);
            if (session == null || !session.getUserId().equals(userId)) {
                result.put("success", false);
                result.put("message", "会话不存在或无权限访问");
                return result;
            }

            // 获取对话记录
            int offset = (page - 1) * size;
            List<TutorMessage> messages = tutorMessageMapper.getMessagesBySessionId(sessionId, offset, size);

            // 获取会话相关的题目信息
            List<TutorQuestion> questions = tutorQuestionMapper.getQuestionsBySessionId(sessionId);

            // 构建响应数据
            Map<String, Object> sessionInfo = buildDetailedSessionInfo(session, questions);
            List<Map<String, Object>> messageList = buildMessageList(messages);

            result.put("success", true);
            result.put("message", "获取对话记录成功");
            result.put("sessionInfo", sessionInfo);
            result.put("messages", messageList);
            result.put("messageCount", tutorMessageMapper.countMessagesBySessionId(sessionId));
            result.put("page", page);
            result.put("size", size);

            log.info("✅ 获取对话记录成功 - 会话: {}, 消息数: {}", session.getSessionName(), messageList.size());

        } catch (Exception e) {
            log.error("❌ 获取对话记录失败", e);
            result.put("success", false);
            result.put("message", "获取对话记录失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 恢复到指定会话
     */
    @PostMapping("/session/{sessionId}/resume")
    @ApiOperation(value = "恢复会话", notes = "恢复到指定会话，可以继续对话")
    public Map<String, Object> resumeSession(
            @ApiParam(value = "会话ID", required = true) @PathVariable Long sessionId,
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("🔄 恢复会话 - 会话ID: {}, 用户ID: {}", sessionId, userId);

            // 验证会话是否存在且属于该用户
            TutorSession session = tutorSessionMapper.selectById(sessionId);
            if (session == null || !session.getUserId().equals(userId)) {
                result.put("success", false);
                result.put("message", "会话不存在或无权限访问");
                return result;
            }

            // 更新会话状态为活跃
            session.setStatus("ACTIVE");
            session.setUpdatedTime(LocalDateTime.now());
            tutorSessionMapper.updateById(session);

            // 获取会话的最新对话记录（最近10条）
            List<TutorMessage> recentMessages = tutorMessageMapper.getMessagesBySessionId(sessionId, 0, 10);

            // 获取会话相关的题目
            List<TutorQuestion> questions = tutorQuestionMapper.getQuestionsBySessionId(sessionId);

            // 构建会话上下文
            String sessionContext = buildSessionResumeContext(session, questions, recentMessages);

            result.put("success", true);
            result.put("message", "会话恢复成功");
            result.put("sessionId", sessionId);
            result.put("sessionName", session.getSessionName());
            result.put("sessionContext", sessionContext);
            result.put("recentMessages", buildMessageList(recentMessages));
            result.put("questions", buildQuestionSummaryList(questions));
            result.put("canContinueChat", true);

            log.info("✅ 会话恢复成功 - 会话: {}", session.getSessionName());

        } catch (Exception e) {
            log.error("❌ 恢复会话失败", e);
            result.put("success", false);
            result.put("message", "恢复会话失败: " + e.getMessage());
        }

        return result;
    }



    /**
     * 删除会话
     */
    @DeleteMapping("/session/{sessionId}")
    @ApiOperation(value = "删除会话", notes = "删除指定会话及其所有相关数据")
    public Map<String, Object> deleteSession(
            @ApiParam(value = "会话ID", required = true) @PathVariable Long sessionId,
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("🗑️ 删除会话 - 会话ID: {}, 用户ID: {}", sessionId, userId);

            // 验证会话是否存在且属于该用户
            TutorSession session = tutorSessionMapper.selectById(sessionId);
            if (session == null || !session.getUserId().equals(userId)) {
                result.put("success", false);
                result.put("message", "会话不存在或无权限访问");
                return result;
            }

            // 删除会话相关的语音文件
            log.info("🗑️ 开始清理会话语音文件...");
            voiceFileService.deleteVoiceFilesBySessionId(sessionId);

            // 软删除会话（设置状态为DELETED）
            session.setStatus("DELETED");
            session.setUpdatedTime(LocalDateTime.now());
            tutorSessionMapper.updateById(session);

            // 软删除相关消息
            List<TutorMessage> messages = tutorMessageMapper.getFullConversationBySessionId(sessionId);
            for (TutorMessage message : messages) {
                message.setIsDeleted(true);
                message.setUpdatedTime(LocalDateTime.now());
                tutorMessageMapper.updateById(message);
            }

            result.put("success", true);
            result.put("message", "会话删除成功");
            result.put("deletedSessionId", sessionId);
            result.put("deletedSessionName", session.getSessionName());

            log.info("✅ 会话删除成功 - 会话: {}", session.getSessionName());

        } catch (Exception e) {
            log.error("❌ 删除会话失败", e);
            result.put("success", false);
            result.put("message", "删除会话失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 生成AI回答的语音播报文件并上传到MinIO
     *
     * @param responseText AI回答文本
     * @return MinIO中的语音文件URL
     */
    private String generateVoiceForResponse(String responseText) {
        return generateVoiceForResponse(responseText, null);
    }

    /**
     * 生成AI回答的语音播报文件并上传到MinIO
     *
     * @param responseText AI回答文本
     * @param messageId 关联的消息ID（可选）
     * @return MinIO中的语音文件URL
     */
    private String generateVoiceForResponse(String responseText, Long messageId) {
        try {
            if (responseText == null || responseText.trim().isEmpty()) {
                log.warn("⚠️ 语音播报文本为空，跳过生成");
                return null;
            }

            // 清理文本，移除Markdown格式和特殊字符
            String cleanText = cleanTextForVoice(responseText);

            if (cleanText.length() > 500) {
                // 如果文本太长，截取前500个字符
                cleanText = cleanText.substring(0, 500) + "...";
                log.info("📝 文本过长，已截取前500字符用于语音播报");
            }

            log.info("🎵 开始生成语音播报 - 文本长度: {}", cleanText.length());

            // 调用VoiceReading类生成本地语音文件
            String localVoiceFilePath = VoiceReading.generateVoiceFile(cleanText);

            if (localVoiceFilePath != null && !localVoiceFilePath.isEmpty()) {
                log.info("✅ 本地语音文件生成成功: {}", localVoiceFilePath);

                // 将语音文件上传到MinIO
                String minioVoiceUrl = voiceFileService.uploadVoiceFileToMinio(localVoiceFilePath, messageId);

                if (minioVoiceUrl != null) {
                    log.info("✅ 语音文件上传到MinIO成功: {}", minioVoiceUrl);
                    return minioVoiceUrl;
                } else {
                    log.error("❌ 语音文件上传到MinIO失败，返回本地路径");
                    return localVoiceFilePath; // 返回本地路径作为备用
                }
            } else {
                log.warn("⚠️ 语音文件生成失败，返回路径为空");
                return null;
            }

        } catch (Exception e) {
            log.error("❌ 生成语音播报失败", e);
            return null;
        }
    }

    /**
     * 清理文本用于语音播报
     * 移除Markdown格式、特殊符号等
     *
     * @param text 原始文本
     * @return 清理后的文本
     */
    private String cleanTextForVoice(String text) {
        if (text == null) {
            return "";
        }

        return text
            // 移除Markdown格式
            .replaceAll("\\*\\*(.*?)\\*\\*", "$1")  // **粗体**
            .replaceAll("\\*(.*?)\\*", "$1")        // *斜体*
            .replaceAll("`(.*?)`", "$1")            // `代码`
            .replaceAll("#{1,6}\\s*", "")           // # 标题
            .replaceAll("\\[(.*?)\\]\\(.*?\\)", "$1") // [链接](url)

            // 移除特殊符号和格式
            .replaceAll("【.*?】[：:]?", "")         // 【标题】：
            .replaceAll("\\n+", "，")               // 换行符替换为逗号
            .replaceAll("\\s+", " ")                // 多个空格合并
            .replaceAll("[\\r\\n\\t]", "")          // 移除制表符等

            // 移除数学公式相关符号（简单处理）
            .replaceAll("\\$.*?\\$", "数学公式")    // LaTeX公式
            .replaceAll("\\\\[a-zA-Z]+\\{.*?\\}", "") // LaTeX命令

            // 移除多余的标点符号
            .replaceAll("[，。]{2,}", "。")          // 多个逗号句号
            .replaceAll("\\s*[，。]\\s*", "，")      // 标点符号前后空格

            .trim();
    }

    /**
     * 从URL中提取文件名
     */
    private String extractFileNameFromUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            return null;
        }

        try {
            // 从URL中提取最后一个/后面的部分作为文件名
            int lastSlashIndex = url.lastIndexOf('/');
            if (lastSlashIndex >= 0 && lastSlashIndex < url.length() - 1) {
                return url.substring(lastSlashIndex + 1);
            }
            return url;
        } catch (Exception e) {
            log.warn("从URL提取文件名失败: {}", url, e);
            return null;
        }
    }

    /**
     * 估算语音时长（基于文本长度）
     */
    private Integer estimateVoiceDuration(String text) {
        if (text == null || text.trim().isEmpty()) {
            return 0;
        }

        // 简单估算：中文每分钟约200字，英文每分钟约150词
        // 这里按照每秒3个字符来估算
        int textLength = text.length();
        return Math.max(1, textLength / 3);
    }

    /**
     * 专门的语音播报接口
     */
    @CrossOrigin(origins = "*", allowedHeaders = "*")
    @PostMapping("/voice-broadcast")
    @ApiOperation(value = "语音播报", notes = "将文本转换为语音播报")
    public Map<String, Object> voiceBroadcast(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "播报文本", required = true) @RequestParam String text) {

        long startTime = System.currentTimeMillis();

        try {
            log.info("🔊 语音播报请求 - 用户ID: {}, 文本长度: {}", userId, text != null ? text.length() : 0);

            // 参数验证
            if (userId == null) {
                log.warn("⚠️ 用户ID为空");
                return buildErrorResponse("用户ID不能为空", "PARAM_ERROR");
            }

            if (text == null || text.trim().isEmpty()) {
                log.warn("⚠️ 播报文本为空");
                return buildErrorResponse("播报文本不能为空", "PARAM_ERROR");
            }

            if (text.length() > 1000) {
                log.warn("⚠️ 播报文本过长: {}", text.length());
                return buildErrorResponse("播报文本长度不能超过1000字符", "TEXT_TOO_LONG");
            }

            // 生成语音文件并上传到MinIO
            String voiceFilePath = generateVoiceForResponse(text.trim());

            if (voiceFilePath != null) {
                // 构建成功响应
                return buildSuccessResponse("语音播报生成成功", Map.of(
                    "originalText", text.trim(),
                    "cleanedText", cleanTextForVoice(text.trim()),
                    "voiceFilePath", voiceFilePath,
                    "userId", userId,
                    "processingTime", System.currentTimeMillis() - startTime,
                    "storageType", voiceFilePath.startsWith("http") ? "MinIO" : "Local"
                ));
            } else {
                return buildErrorResponse("语音播报生成失败", "VOICE_GENERATION_ERROR");
            }

        } catch (Exception e) {
            log.error("❌ 语音播报失败 - 用户ID: {}, 错误: {}", userId, e.getMessage(), e);
            return buildErrorResponse("语音播报失败: " + e.getMessage(), "VOICE_BROADCAST_ERROR");
        }
    }

    /**
     * 语音文件下载接口 - 从MinIO获取
     */
    @CrossOrigin(origins = "*", allowedHeaders = "*")
    @GetMapping("/voice-file/{fileName}")
    @ApiOperation(value = "下载语音文件", notes = "根据文件名从MinIO下载生成的语音文件")
    public ResponseEntity<Resource> downloadVoiceFile(
            @ApiParam(value = "语音文件名", required = true) @PathVariable String fileName,
            HttpServletRequest request) {

        try {
            log.info("📥 语音文件下载请求 - 文件名: {}", fileName);

            // 安全检查：只允许下载mp3文件，支持UUID格式
            if (!fileName.endsWith(".mp3")) {
                log.warn("⚠️ 非法的语音文件格式: {}", fileName);
                return ResponseEntity.badRequest().build();
            }

            // 检查是否是有效的语音文件名（支持ai_voice_开头或UUID格式）
            boolean isValidVoiceFile = fileName.startsWith("ai_voice_") ||
                                     fileName.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\.mp3$");

            if (!isValidVoiceFile) {
                log.warn("⚠️ 不支持的语音文件名格式: {}", fileName);
                return ResponseEntity.badRequest().build();
            }

            // 尝试从MinIO获取文件
            // 首先尝试直接使用文件名（兼容旧格式）
            String voiceFileName = fileName;
            boolean fileExists = voiceFileService.voiceFileExists(voiceFileName);

            if (!fileExists) {
                // 如果直接文件名不存在，尝试在voice目录结构中查找
                String currentDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
                voiceFileName = "voice/" + currentDate + "/" + fileName;
                fileExists = voiceFileService.voiceFileExists(voiceFileName);

                if (!fileExists) {
                    // 尝试查找最近几天的文件
                    for (int i = 1; i <= 7; i++) {
                        String pastDate = LocalDateTime.now().minusDays(i).format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
                        voiceFileName = "voice/" + pastDate + "/" + fileName;
                        if (voiceFileService.voiceFileExists(voiceFileName)) {
                            fileExists = true;
                            break;
                        }
                    }
                }
            }

            if (!fileExists) {
                log.warn("⚠️ 语音文件在MinIO中不存在: {}", fileName);
                return ResponseEntity.notFound().build();
            }

            // 从MinIO获取文件流
            InputStream inputStream = minioService.downloadFileFromSpecificBucket(voiceFileName, "video");

            if (inputStream == null) {
                log.warn("⚠️ 无法从MinIO获取语音文件: {}", voiceFileName);
                return ResponseEntity.notFound().build();
            }

            // 创建资源对象
            Resource resource = new InputStreamResource(inputStream);

            log.info("✅ 语音文件下载成功 - 文件: {}", voiceFileName);

            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType("audio/mpeg"))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + fileName + "\"")
                    .header(HttpHeaders.CACHE_CONTROL, "public, max-age=3600")
                    .header("Accept-Ranges", "bytes")
                    .header("Access-Control-Allow-Origin", "*")
                    .header("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS")
                    .header("Access-Control-Allow-Headers", "*")
                    .body(resource);

        } catch (Exception e) {
            log.error("❌ 语音文件下载失败 - 文件名: {}, 错误: {}", fileName, e.getMessage(), e);
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 语音文件下载CORS预检请求处理
     */
    @CrossOrigin(origins = "*", allowedHeaders = "*")
    @RequestMapping(value = "/voice-file/{fileName}", method = RequestMethod.OPTIONS)
    @ApiOperation(value = "语音文件下载CORS预检", notes = "处理语音文件下载的CORS预检请求")
    public ResponseEntity<Void> downloadVoiceFileOptions(@PathVariable String fileName) {
        return ResponseEntity.ok()
                .header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS")
                .header("Access-Control-Allow-Headers", "*")
                .header("Access-Control-Max-Age", "3600")
                .build();
    }





    // ==================== 辅助方法 ====================

    /**
     * 构建会话信息
     */
    private Map<String, Object> buildSessionInfo(TutorSession session) {
        Map<String, Object> sessionInfo = new HashMap<>();

        try {
            sessionInfo.put("sessionId", session.getId());
            sessionInfo.put("sessionName", session.getSessionName());
            sessionInfo.put("sessionType", session.getSessionType());
            sessionInfo.put("status", session.getStatus());
            sessionInfo.put("createdTime", session.getCreatedTime());
            sessionInfo.put("lastMessageTime", session.getLastMessageTime());

            // 获取会话统计信息
            Integer messageCount = tutorMessageMapper.countMessagesBySessionId(session.getId());
            List<TutorQuestion> questions = tutorQuestionMapper.getQuestionsBySessionId(session.getId());
            TutorMessage lastMessage = tutorMessageMapper.getLastMessageBySessionId(session.getId());

            sessionInfo.put("messageCount", messageCount);
            sessionInfo.put("questionCount", questions.size());
            sessionInfo.put("lastMessage", lastMessage != null ? lastMessage.getContent() : "暂无消息");
            sessionInfo.put("lastMessageTime", lastMessage != null ? lastMessage.getCreatedTime() : session.getCreatedTime());

            // 计算会话活跃度
            long daysSinceLastMessage = java.time.Duration.between(
                session.getLastMessageTime() != null ? session.getLastMessageTime() : session.getCreatedTime(),
                LocalDateTime.now()
            ).toDays();
            sessionInfo.put("daysSinceLastMessage", daysSinceLastMessage);
            sessionInfo.put("isActive", daysSinceLastMessage <= 7); // 7天内有活动算活跃

        } catch (Exception e) {
            log.error("构建会话信息失败", e);
        }

        return sessionInfo;
    }

    /**
     * 构建详细会话信息
     */
    private Map<String, Object> buildDetailedSessionInfo(TutorSession session, List<TutorQuestion> questions) {
        Map<String, Object> sessionInfo = buildSessionInfo(session);

        try {
            // 添加题目详细信息
            List<Map<String, Object>> questionDetails = new ArrayList<>();
            for (TutorQuestion question : questions) {
                Map<String, Object> questionInfo = new HashMap<>();
                questionInfo.put("questionId", question.getId());
                questionInfo.put("ocrText", question.getOcrText());
                questionInfo.put("subject", question.getSubject());
                questionInfo.put("questionType", question.getQuestionType());
                questionInfo.put("difficultyLevel", question.getDifficultyLevel());
                questionInfo.put("finalAnswer", question.getFinalAnswer());
                questionInfo.put("createdTime", question.getCreatedTime());
                questionInfo.put("imageUrl", question.getImageUrl());
                questionDetails.add(questionInfo);
            }
            sessionInfo.put("questionDetails", questionDetails);

            // 添加会话摘要
            if (!questions.isEmpty()) {
                Map<String, Long> subjectCount = questions.stream()
                    .collect(Collectors.groupingBy(
                        q -> q.getSubject() != null ? q.getSubject() : "未知",
                        Collectors.counting()
                    ));
                sessionInfo.put("subjectDistribution", subjectCount);

                double avgDifficulty = questions.stream()
                    .filter(q -> q.getDifficultyLevel() != null)
                    .mapToInt(TutorQuestion::getDifficultyLevel)
                    .average()
                    .orElse(0.0);
                sessionInfo.put("averageDifficulty", Math.round(avgDifficulty * 10.0) / 10.0);
            }

        } catch (Exception e) {
            log.error("构建详细会话信息失败", e);
        }

        return sessionInfo;
    }

    /**
     * 构建消息列表
     */
    private List<Map<String, Object>> buildMessageList(List<TutorMessage> messages) {
        List<Map<String, Object>> messageList = new ArrayList<>();

        try {
            for (TutorMessage message : messages) {
                Map<String, Object> messageInfo = new HashMap<>();
                messageInfo.put("messageId", message.getId());
                messageInfo.put("messageType", message.getMessageType());
                messageInfo.put("content", message.getContent());
                messageInfo.put("contentType", message.getContentType());
                messageInfo.put("createdTime", message.getCreatedTime());
                messageInfo.put("parentMessageId", message.getParentMessageId());

                // 解析元数据
                if (message.getMetadata() != null) {
                    try {
                        @SuppressWarnings("unchecked")
                        Map<String, Object> metadata = JSON.parseObject(message.getMetadata(), Map.class);
                        messageInfo.put("metadata", metadata);
                    } catch (Exception e) {
                        messageInfo.put("metadata", null);
                    }
                }

                messageList.add(messageInfo);
            }
        } catch (Exception e) {
            log.error("构建消息列表失败", e);
        }

        return messageList;
    }

    /**
     * 构建会话恢复上下文
     */
    private String buildSessionResumeContext(TutorSession session, List<TutorQuestion> questions, List<TutorMessage> recentMessages) {
        StringBuilder context = new StringBuilder();

        try {
            context.append("=== 会话恢复信息 ===\n");
            context.append("会话名称：").append(session.getSessionName()).append("\n");
            context.append("创建时间：").append(session.getCreatedTime()).append("\n");
            context.append("最后活动：").append(session.getLastMessageTime()).append("\n\n");

            // 添加题目摘要
            if (!questions.isEmpty()) {
                context.append("=== 题目摘要 ===\n");
                for (int i = 0; i < Math.min(3, questions.size()); i++) {
                    TutorQuestion question = questions.get(i);
                    context.append(String.format("%d. %s (%s)\n",
                        i + 1,
                        question.getOcrText().length() > 50 ?
                            question.getOcrText().substring(0, 50) + "..." : question.getOcrText(),
                        question.getSubject()));
                }
                if (questions.size() > 3) {
                    context.append("... 还有").append(questions.size() - 3).append("道题目\n");
                }
                context.append("\n");
            }

            // 添加最近对话
            if (!recentMessages.isEmpty()) {
                context.append("=== 最近对话 ===\n");
                for (TutorMessage message : recentMessages) {
                    String role = TutorMessage.MESSAGE_TYPE_USER.equals(message.getMessageType()) ? "用户" : "AI";
                    String content = message.getContent().length() > 100 ?
                        message.getContent().substring(0, 100) + "..." : message.getContent();
                    context.append(role).append("：").append(content).append("\n");
                }
                context.append("\n");
            }

            context.append("您现在可以继续这个会话的对话。");

        } catch (Exception e) {
            log.error("构建会话恢复上下文失败", e);
            context.append("会话恢复成功，您可以继续对话。");
        }

        return context.toString();
    }

    /**
     * 构建题目摘要列表
     */
    private List<Map<String, Object>> buildQuestionSummaryList(List<TutorQuestion> questions) {
        List<Map<String, Object>> summaryList = new ArrayList<>();

        try {
            for (TutorQuestion question : questions) {
                Map<String, Object> summary = new HashMap<>();
                summary.put("questionId", question.getId());
                summary.put("ocrText", question.getOcrText().length() > 100 ?
                    question.getOcrText().substring(0, 100) + "..." : question.getOcrText());
                summary.put("subject", question.getSubject());
                summary.put("questionType", question.getQuestionType());
                summary.put("difficultyLevel", question.getDifficultyLevel());
                summary.put("finalAnswer", question.getFinalAnswer());
                summary.put("createdTime", question.getCreatedTime());
                summaryList.add(summary);
            }
        } catch (Exception e) {
            log.error("构建题目摘要列表失败", e);
        }

        return summaryList;
    }

    /**
     * 构建题目结果
     */
    private Map<String, Object> buildQuestionResult(QuestionRecord question) {
        Map<String, Object> result = new HashMap<>();
        result.put("questionId", question.getId());
        result.put("questionText", question.getQuestionText());
        result.put("questionType", question.getQuestionType());
        result.put("subject", question.getSubject());
        result.put("analysis", question.getAnalysis());
        result.put("solutionSteps", question.getSolutionSteps());
        result.put("finalAnswer", question.getFinalAnswer());
        result.put("imagePath", question.getImagePath());
        result.put("createTime", question.getCreateTime());
        return result;
    }

    /**
     * 构建题目上下文信息
     */
    private String buildQuestionContext(QuestionRecord question) {
        StringBuilder context = new StringBuilder();
        context.append("=== 题目信息 ===\n");
        context.append("题目内容：").append(question.getQuestionText()).append("\n");
        if (question.getSubject() != null) {
            context.append("学科：").append(question.getSubject()).append("\n");
        }
        if (question.getQuestionType() != null) {
            context.append("题型：").append(question.getQuestionType()).append("\n");
        }
        if (question.getAnalysis() != null) {
            context.append("AI分析：").append(question.getAnalysis()).append("\n");
        }
        context.append("=== 题目信息结束 ===\n");
        return context.toString();
    }

    /**
     * 生成相似题目
     */
    private List<Map<String, Object>> generateSimilarQuestions(String originalText) {
        List<Map<String, Object>> similarQuestions = new ArrayList<>();

        try {
            // 使用AI服务生成相似题目
            String similarQuestionsJson = aiChatService.generateSimilarQuestions(originalText, 3);

            // 尝试解析AI返回的JSON
            try {
                List<Map<String, Object>> aiGeneratedQuestions = safeParseJsonArray(similarQuestionsJson);

                for (int i = 0; i < aiGeneratedQuestions.size() && i < 3; i++) {
                    Map<String, Object> aiQuestion = aiGeneratedQuestions.get(i);
                    Map<String, Object> similar = new HashMap<>();

                    similar.put("id", System.currentTimeMillis() + i);
                    similar.put("questionText", aiQuestion.get("question"));
                    similar.put("answer", aiQuestion.get("answer"));
                    similar.put("explanation", aiQuestion.get("explanation"));
                    similar.put("generatedBy", "AI");

                    similarQuestions.add(similar);
                }

            } catch (Exception parseException) {
                log.warn("⚠️ AI返回的JSON解析失败，使用纯AI备用方案", parseException);
                // 使用纯AI备用方案生成相似题目
                similarQuestions = generatePureAiFallbackQuestions(originalText);
            }

        } catch (Exception e) {
            log.error("❌ AI生成相似题目失败，使用纯AI备用方案", e);
            similarQuestions = generatePureAiFallbackQuestions(originalText);
        }

        return similarQuestions;
    }

    /**
     * 纯AI备用方案：生成相似题目
     */
    private List<Map<String, Object>> generatePureAiFallbackQuestions(String originalText) {
        List<Map<String, Object>> fallbackQuestions = new ArrayList<>();

        try {
            log.info("🔄 使用纯AI备用方案生成相似题目...");

            // 使用更简单的提示词重新尝试
            String simplifiedPrompt = String.format("""
                请基于题目"%s"生成3道相似题目。
                要求：
                1. 保持相同知识点
                2. 改变数值或条件
                3. 返回JSON格式：[{"question":"题目","answer":"答案","explanation":"解释"}]
                """, originalText.length() > 200 ? originalText.substring(0, 200) + "..." : originalText);

            String aiResponse = aiChatService.chat(simplifiedPrompt);

            // 尝试解析简化的AI响应
            try {
                List<Map<String, Object>> aiQuestions = safeParseJsonArray(aiResponse);

                for (int i = 0; i < Math.min(3, aiQuestions.size()); i++) {
                    Map<String, Object> aiQuestion = aiQuestions.get(i);
                    Map<String, Object> similar = new HashMap<>();

                    similar.put("id", "pure_ai_" + System.currentTimeMillis() + "_" + i);
                    similar.put("questionText", aiQuestion.get("question"));
                    similar.put("answer", aiQuestion.get("answer"));
                    similar.put("explanation", aiQuestion.get("explanation"));
                    similar.put("generatedBy", "PURE_AI_FALLBACK");
                    similar.put("generatedTime", LocalDateTime.now());

                    fallbackQuestions.add(similar);
                }

                log.info("✅ 纯AI备用方案成功生成{}道题目", fallbackQuestions.size());

            } catch (Exception parseError) {
                log.warn("⚠️ 纯AI备用方案解析失败，使用最终模板方案", parseError);
                fallbackQuestions = generateFinalTemplateFallback(originalText);
            }

        } catch (Exception e) {
            log.warn("⚠️ 纯AI备用方案失败，使用最终模板方案", e);
            fallbackQuestions = generateFinalTemplateFallback(originalText);
        }

        return fallbackQuestions;
    }

    /**
     * 最终模板备用方案
     */
    private List<Map<String, Object>> generateFinalTemplateFallback(String originalText) {
        List<Map<String, Object>> templateQuestions = new ArrayList<>();

        for (int i = 1; i <= 3; i++) {
            Map<String, Object> similar = new HashMap<>();
            similar.put("id", "template_final_" + System.currentTimeMillis() + "_" + i);
            similar.put("questionText", String.format("相似题目 %d：基于原题目的变化练习", i));
            similar.put("answer", "请根据题目要求进行分析和计算");
            similar.put("explanation", "这是一道与原题相似的练习题，请运用相同的解题方法");
            similar.put("generatedBy", "FINAL_TEMPLATE");
            similar.put("generatedTime", LocalDateTime.now());

            templateQuestions.add(similar);
        }

        log.info("📝 最终模板方案生成{}道题目", templateQuestions.size());
        return templateQuestions;
    }



    /**
     * 生成相似题目文本
     */
    private String generateSimilarQuestionText(String originalText, int index) {
        if (originalText == null) return "相似题目 " + index;

        String[] variations = {
            "类似题目：" + originalText.replace("求", "计算"),
            "相关练习：" + originalText.replace("已知", "设"),
            "举一反三：" + originalText.replace("的值", "的结果")
        };

        return variations[(index - 1) % variations.length];
    }

    // ==================== 统一响应构建方法 ====================

    /**
     * 构建成功响应
     */
    private Map<String, Object> buildSuccessResponse(String message, Object data) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("message", message);
        response.put("data", data);
        response.put("timestamp", System.currentTimeMillis());
        return response;
    }

    /**
     * 构建错误响应
     */
    private Map<String, Object> buildErrorResponse(String message, String errorCode) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", false);
        response.put("message", message);
        response.put("errorCode", errorCode);
        response.put("timestamp", System.currentTimeMillis());
        return response;
    }

    /**
     * 构建上下文消息
     */
    private String buildContextMessage(Long userId, String sessionId, String currentMessage) {
        try {
            // 从Redis获取该会话的历史消息
            String historyKey = "chat_history:" + userId + ":" + sessionId;
            String historyJson = RedisUtil.getString(historyKey);

            if (historyJson != null && !historyJson.isEmpty()) {
                // 解析历史消息并构建上下文
                List<Map> history = JSON.parseArray(historyJson, Map.class);
                StringBuilder contextBuilder = new StringBuilder();

                // 添加最近的几条对话作为上下文（最多5条）
                int contextCount = Math.min(history.size(), 5);
                for (int i = Math.max(0, history.size() - contextCount); i < history.size(); i++) {
                    Map msg = history.get(i);
                    contextBuilder.append("用户: ").append(msg.get("user")).append("\n");
                    contextBuilder.append("AI: ").append(msg.get("ai")).append("\n");
                }

                contextBuilder.append("用户: ").append(currentMessage);
                return contextBuilder.toString();
            }
        } catch (Exception e) {
            log.warn("构建上下文消息失败: {}", e.getMessage());
        }

        return currentMessage;
    }

    /**
     * 保存对话记录
     */
    private void saveConversationRecord(Long userId, String sessionId, String userMessage, String aiResponse) {
        try {
            String historyKey = "chat_history:" + userId + ":" + sessionId;
            log.info("💬 保存对话记录，Redis键: {}", historyKey);

            String historyJson = RedisUtil.getString(historyKey);
            log.info("📄 现有对话历史: {}", historyJson);

            List<Map> history;
            if (historyJson != null && !historyJson.isEmpty()) {
                history = JSON.parseArray(historyJson, Map.class);
                log.info("📋 现有对话数量: {}", history.size());
            } else {
                history = new ArrayList<>();
                log.info("📋 没有现有对话，创建新列表");
            }

            // 添加新的对话记录
            Map<String, Object> newRecord = new HashMap<>();
            newRecord.put("id", System.currentTimeMillis());
            newRecord.put("type", "conversation");
            newRecord.put("user", userMessage);
            newRecord.put("ai", aiResponse);
            newRecord.put("timestamp", System.currentTimeMillis());

            history.add(newRecord);
            log.info("➕ 添加新对话记录，总数量: {}", history.size());

            // 保持最多100条历史记录
            if (history.size() > 100) {
                history = history.subList(history.size() - 100, history.size());
                log.info("✂️ 限制对话记录为100条");
            }

            // 保存到Redis，30天过期
            String jsonData = JSON.toJSONString(history);
            log.info("💾 保存对话到Redis，键: {}, 数据长度: {}", historyKey, jsonData.length());

            RedisUtil.setString(historyKey, jsonData, 2592000);
            log.info("✅ 对话记录Redis保存完成");

            // 更新会话信息
            updateSessionInfo(userId, sessionId, history.size());

            log.info("✅ 保存对话记录成功 - 用户: {}, 会话: {}, 历史记录数: {}", userId, sessionId, history.size());

        } catch (Exception e) {
            log.error("❌ 保存对话记录失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 更新会话信息
     */
    private void updateSessionInfo(Long userId, String sessionId, int messageCount) {
        try {
            String sessionsKey = "user_sessions:" + userId;
            String sessionsJson = RedisUtil.getString(sessionsKey);

            if (sessionsJson != null && !sessionsJson.isEmpty()) {
                List<Map> sessions = JSON.parseArray(sessionsJson, Map.class);

                // 找到对应的会话并更新
                for (Map session : sessions) {
                    if (sessionId.equals(session.get("id"))) {
                        session.put("updateTime", System.currentTimeMillis());
                        session.put("messageCount", messageCount);
                        break;
                    }
                }

                // 保存更新后的会话列表
                RedisUtil.setString(sessionsKey, JSON.toJSONString(sessions), 2592000);
            }

        } catch (Exception e) {
            log.error("更新会话信息失败: {}", e.getMessage(), e);
        }
    }







    /**
     * 生成相似题目接口
     */
    @PostMapping("/generate-similar")
    @ApiOperation(value = "生成相似题目", notes = "基于题目文本生成相似题目")
    public Map<String, Object> generateSimilarQuestions(
            @ApiParam(value = "题目文本", required = true) @RequestParam String questionText,
            @ApiParam(value = "生成数量", required = false) @RequestParam(defaultValue = "3") Integer count) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("🔄 生成相似题目 - 题目: {}, 数量: {}", questionText, count);

            List<Map<String, Object>> similarQuestions = generateSimilarQuestions(questionText);

            result.put("success", true);
            result.put("message", "生成相似题目成功");
            result.put("data", similarQuestions);

            log.info("✅ 生成相似题目成功 - 生成 {} 道题目", similarQuestions.size());

        } catch (Exception e) {
            log.error("❌ 生成相似题目失败", e);
            result.put("success", false);
            result.put("message", "生成相似题目失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 获取用户搜题历史记录
     *
     * @param userId 用户ID（可选）
     * @param page 页码，默认为1
     * @param size 每页大小，默认为20
     * @return ResponseEntity 包含搜索历史的响应实体
     */
    @GetMapping("/search-history")
    @ApiOperation(value = "获取搜题历史", notes = "获取用户的搜题历史记录，支持分页查询")
    public Map<String, Object> getSearchHistory(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "页码", required = false) @RequestParam(defaultValue = "1") int page,
            @ApiParam(value = "每页大小", required = false) @RequestParam(defaultValue = "20") int size) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("🔄 获取搜题历史 - 用户ID: {}, 页码: {}, 每页大小: {}", userId, page, size);

            // 计算偏移量
            int offset = (page - 1) * size;

            // 从数据库查询用户的搜题记录
            List<TutorQuestion> questions = tutorQuestionMapper.selectByUserIdWithPagination(userId, offset, size);
            Long total = tutorQuestionMapper.countByUserId(userId);

            // 构建返回数据
            List<Map<String, Object>> questionList = new ArrayList<>();
            for (TutorQuestion question : questions) {
                Map<String, Object> questionMap = new HashMap<>();
                questionMap.put("id", question.getId());
                questionMap.put("userId", question.getUserId());
                questionMap.put("sessionId", question.getSessionId());
                questionMap.put("questionText", question.getQuestionText());
                questionMap.put("ocrText", question.getOcrText());
                questionMap.put("ocrLatex", question.getOcrLatex());
                questionMap.put("imageUrl", question.getImageUrl());
                questionMap.put("imageHash", question.getImageHash());
                questionMap.put("aiAnalysis", question.getAiAnalysis());
                questionMap.put("similarQuestions", question.getSimilarQuestions());
                questionMap.put("createdTime", question.getCreatedTime());
                questionMap.put("updatedTime", question.getUpdatedTime());
                questionMap.put("masteryStatus", question.getMasteryStatus() != null ? question.getMasteryStatus() : 0);
                questionMap.put("isWrong", question.getIsWrong() != null ? question.getIsWrong() : false);

                questionList.add(questionMap);
            }

            result.put("code", 200);
            result.put("message", "获取搜题历史成功");
            result.put("data", Map.of(
                "questions", questionList,
                "total", total,
                "page", page,
                "size", size,
                "hasMore", (page * size) < total
            ));

            log.info("✅ 获取搜题历史成功 - 返回 {} 条记录，总计 {} 条", questionList.size(), total);

        } catch (Exception e) {
            log.error("❌ 获取搜题历史失败", e);
            result.put("code", 500);
            result.put("message", "获取搜题历史失败：" + e.getMessage());
        }

        return result;
    }



    /**
     * 删除会话
     */
    @DeleteMapping("/sessions/{sessionId}")
    @ApiOperation(value = "删除会话", notes = "删除指定的会话及其所有消息")
    public Map<String, Object> deleteSession(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "会话ID", required = true) @PathVariable String sessionId) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("🗑️ 删除会话 - 用户ID: {}, 会话ID: {}", userId, sessionId);

            // 删除会话消息
            deleteSessionMessagesFromRedis(sessionId);

            // 从会话列表中删除
            deleteSessionFromRedis(userId, sessionId);

            result.put("success", true);
            result.put("message", "删除会话成功");
            result.put("data", Map.of("deletedSessionId", sessionId));

            log.info("✅ 删除会话成功 - 会话ID: {}", sessionId);

        } catch (Exception e) {
            log.error("❌ 删除会话失败 - 用户ID: {}, 会话ID: {}", userId, sessionId, e);
            result.put("success", false);
            result.put("message", "删除会话失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 获取会话消息
     */
    @GetMapping("/sessions/{sessionId}/messages")
    @ApiOperation(value = "获取会话消息", notes = "获取指定会话的所有消息")
    public Map<String, Object> getSessionMessages(
            @ApiParam(value = "用户ID", required = true) @RequestParam Long userId,
            @ApiParam(value = "会话ID", required = true) @PathVariable String sessionId) {

        Map<String, Object> result = new HashMap<>();

        try {
            log.info("💬 获取会话消息 - 用户ID: {}, 会话ID: {}", userId, sessionId);

            // 从Redis获取消息
            List<Map<String, Object>> messages = getMessagesFromRedis(sessionId);

            result.put("success", true);
            result.put("message", "获取消息成功");
            result.put("data", Map.of(
                "sessionId", sessionId,
                "messages", messages,
                "count", messages.size()
            ));

            log.info("✅ 获取会话消息成功 - 会话ID: {}, 消息数量: {}", sessionId, messages.size());

        } catch (Exception e) {
            log.error("❌ 获取会话消息失败 - 用户ID: {}, 会话ID: {}", userId, sessionId, e);
            result.put("success", false);
            result.put("message", "获取消息失败: " + e.getMessage());
        }

        return result;
    }

    // ==================== Redis会话管理方法 ====================

    /**
     * 从Redis获取用户会话列表
     */
    private List<Map<String, Object>> getSessionsFromRedis(Long userId) {
        try {
            String redisKey = "tutor:sessions:user:" + userId;
            String sessionsJson = RedisUtil.getString(redisKey);

            if (sessionsJson != null && !sessionsJson.trim().isEmpty()) {
                List<Map> rawList = JSON.parseArray(sessionsJson, Map.class);
                List<Map<String, Object>> result = new ArrayList<>();
                for (Map map : rawList) {
                    result.add((Map<String, Object>) map);
                }
                return result;
            }
        } catch (Exception e) {
            log.error("从Redis获取会话列表失败 - 用户ID: {}", userId, e);
        }
        return new ArrayList<>();
    }

    /**
     * 保存会话列表到Redis
     */
    private void saveSessionsToRedis(Long userId, List<Map<String, Object>> sessions) {
        try {
            String redisKey = "tutor:sessions:user:" + userId;
            String sessionsJson = JSON.toJSONString(sessions);
            RedisUtil.setString(redisKey, sessionsJson, 86400 * 7); // 7天过期
            log.info("保存会话列表到Redis成功 - 用户ID: {}, 会话数量: {}", userId, sessions.size());
        } catch (Exception e) {
            log.error("保存会话列表到Redis失败 - 用户ID: {}", userId, e);
        }
    }

    /**
     * 保存单个会话到Redis
     */
    private void saveSessionToRedis(Long userId, Map<String, Object> session) {
        try {
            // 获取现有会话列表
            List<Map<String, Object>> sessions = getSessionsFromRedis(userId);

            // 添加新会话到列表开头
            sessions.add(0, session);

            // 限制最多保存50个会话
            if (sessions.size() > 50) {
                sessions = sessions.subList(0, 50);
            }

            // 保存回Redis
            saveSessionsToRedis(userId, sessions);

            log.info("保存单个会话到Redis成功 - 用户ID: {}, 会话ID: {}", userId, session.get("id"));
        } catch (Exception e) {
            log.error("保存单个会话到Redis失败 - 用户ID: {}", userId, e);
        }
    }

    /**
     * 从Redis删除会话
     */
    private void deleteSessionFromRedis(Long userId, String sessionId) {
        try {
            List<Map<String, Object>> sessions = getSessionsFromRedis(userId);
            sessions.removeIf(session -> sessionId.equals(session.get("id")));
            saveSessionsToRedis(userId, sessions);
            log.info("从Redis删除会话成功 - 用户ID: {}, 会话ID: {}", userId, sessionId);
        } catch (Exception e) {
            log.error("从Redis删除会话失败 - 用户ID: {}, 会话ID: {}", userId, sessionId, e);
        }
    }

    /**
     * 从Redis删除会话消息
     */
    private void deleteSessionMessagesFromRedis(String sessionId) {
        try {
            String messagesKey = "tutor:messages:session:" + sessionId;
            RedisUtil.del(messagesKey);
            log.info("从Redis删除会话消息成功 - 会话ID: {}", sessionId);
        } catch (Exception e) {
            log.error("从Redis删除会话消息失败 - 会话ID: {}", sessionId, e);
        }
    }

    /**
     * 将数据库会话转换为Redis格式
     */
    private List<Map<String, Object>> convertSessionsToRedisFormat(List<TutorSession> dbSessions) {
        List<Map<String, Object>> sessions = new ArrayList<>();

        for (TutorSession dbSession : dbSessions) {
            Map<String, Object> session = new HashMap<>();
            session.put("id", dbSession.getId().toString());
            session.put("title", dbSession.getSessionName());
            session.put("userId", dbSession.getUserId());
            session.put("createTime", dbSession.getCreatedTime().toString());
            session.put("updateTime", dbSession.getUpdatedTime().toString());
            session.put("messageCount", getMessageCountBySessionId(dbSession.getId()));
            session.put("status", dbSession.getStatus());
            sessions.add(session);
        }

        return sessions;
    }

    /**
     * 生成会话ID
     */
    private String generateSessionId() {
        return "session_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000);
    }

    /**
     * 获取会话消息数量
     */
    private int getMessageCountBySessionId(Long sessionId) {
        try {
            return tutorMessageMapper.countMessagesBySessionId(sessionId);
        } catch (Exception e) {
            log.warn("获取会话消息数量失败 - 会话ID: {}", sessionId, e);
            return 0;
        }
    }

    /**
     * 保存消息到Redis
     */
    private void saveMessageToRedis(Long userId, String sessionId, String userMessage, String aiResponse) {
        try {
            String messagesKey = "tutor:messages:session:" + sessionId;
            log.info("💾 保存消息到Redis - 键: {}, 用户消息: {}, AI回复: {}", messagesKey, userMessage, aiResponse);

            // 获取现有消息
            String messagesJson = RedisUtil.getString(messagesKey);
            List<Map<String, Object>> messages = new ArrayList<>();

            if (messagesJson != null && !messagesJson.trim().isEmpty()) {
                List<Map> rawList = JSON.parseArray(messagesJson, Map.class);
                for (Map map : rawList) {
                    messages.add((Map<String, Object>) map);
                }
                log.info("📋 现有消息数量: {}", messages.size());
            } else {
                log.info("📋 没有现有消息，创建新的消息列表");
            }

            // 添加用户消息
            Map<String, Object> userMsg = new HashMap<>();
            userMsg.put("id", System.currentTimeMillis());
            userMsg.put("type", "user");
            userMsg.put("content", userMessage);
            userMsg.put("timestamp", LocalDateTime.now().toString());
            messages.add(userMsg);

            // 添加AI回复
            Map<String, Object> aiMsg = new HashMap<>();
            aiMsg.put("id", System.currentTimeMillis() + 1);
            aiMsg.put("type", "ai");
            aiMsg.put("content", aiResponse);
            aiMsg.put("timestamp", LocalDateTime.now().toString());
            messages.add(aiMsg);

            // 限制消息数量（最多保存100条）
            if (messages.size() > 100) {
                messages = messages.subList(messages.size() - 100, messages.size());
            }

            // 保存到Redis
            String finalJson = JSON.toJSONString(messages);
            log.info("📤 准备保存到Redis的JSON: {}", finalJson);

            RedisUtil.setString(messagesKey, finalJson, 86400 * 7); // 7天过期

            log.info("✅ 保存消息到Redis成功 - 会话ID: {}, 消息数量: {}", sessionId, messages.size());

            // 验证保存是否成功
            String verifyJson = RedisUtil.getString(messagesKey);
            log.info("🔍 验证保存结果 - 从Redis读取: {}", verifyJson);

        } catch (Exception e) {
            log.error("❌ 保存消息到Redis失败 - 会话ID: {}", sessionId, e);
        }
    }

    /**
     * 从Redis获取会话消息
     */
    private List<Map<String, Object>> getMessagesFromRedis(String sessionId) {
        try {
            String messagesKey = "tutor:messages:session:" + sessionId;
            log.info("🔍 从Redis获取消息 - 键: {}", messagesKey);

            String messagesJson = RedisUtil.getString(messagesKey);
            log.info("📄 Redis返回的JSON数据: {}", messagesJson);

            if (messagesJson != null && !messagesJson.trim().isEmpty()) {
                List<Map> rawList = JSON.parseArray(messagesJson, Map.class);
                List<Map<String, Object>> result = new ArrayList<>();
                for (Map map : rawList) {
                    result.add((Map<String, Object>) map);
                }
                log.info("📝 转换后的消息列表: {}", result);
                return result;
            } else {
                log.info("⚠️ Redis中没有找到消息数据 - 会话ID: {}", sessionId);
            }
        } catch (Exception e) {
            log.error("从Redis获取会话消息失败 - 会话ID: {}", sessionId, e);
        }
        return new ArrayList<>();
    }

    /**
     * 从历史消息构建上下文
     */
    private String buildContextMessageFromHistory(List<Map<String, Object>> historyMessages, String newMessage) {
        StringBuilder context = new StringBuilder();

        // 只取最近的10条消息作为上下文
        int startIndex = Math.max(0, historyMessages.size() - 10);
        List<Map<String, Object>> recentMessages = historyMessages.subList(startIndex, historyMessages.size());

        if (!recentMessages.isEmpty()) {
            context.append("以下是我们之前的对话历史：\n\n");

            for (Map<String, Object> message : recentMessages) {
                String type = (String) message.get("type");
                String content = (String) message.get("content");

                if ("user".equals(type)) {
                    context.append("用户：").append(content).append("\n");
                } else if ("ai".equals(type)) {
                    context.append("AI：").append(content).append("\n");
                }
            }

            context.append("\n现在用户的新问题是：").append(newMessage);
            context.append("\n\n请基于上述对话历史，回答用户的新问题。保持回答的连贯性和相关性。");
        } else {
            context.append(newMessage);
        }

        return context.toString();
    }
}
